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
34 #include "alAuxEffectSlot.h"
37 enum Resampler DefaultResampler
= LinearResampler
;
38 const ALsizei ResamplerPadding
[ResamplerMax
] = {
43 const ALsizei ResamplerPrePadding
[ResamplerMax
] = {
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 static ALenum
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALfloat
*values
);
57 static ALenum
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALint
*values
);
59 static ALenum
GetSourcedv(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALdouble
*values
);
60 static ALenum
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint
*values
);
61 static ALenum
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint64
*values
);
64 #define RETERR(x) do { \
65 alSetError(Context, (x)); \
69 #define CHECKVAL(x) do { \
71 RETERR(AL_INVALID_VALUE); \
74 static ALenum
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALfloat
*values
)
79 CHECKVAL(*values
>= 0.0f
);
81 Source
->Pitch
= *values
;
82 Source
->NeedsUpdate
= AL_TRUE
;
85 case AL_CONE_INNER_ANGLE
:
86 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
88 Source
->InnerAngle
= *values
;
89 Source
->NeedsUpdate
= AL_TRUE
;
92 case AL_CONE_OUTER_ANGLE
:
93 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
95 Source
->OuterAngle
= *values
;
96 Source
->NeedsUpdate
= AL_TRUE
;
100 CHECKVAL(*values
>= 0.0f
);
102 Source
->Gain
= *values
;
103 Source
->NeedsUpdate
= AL_TRUE
;
106 case AL_MAX_DISTANCE
:
107 CHECKVAL(*values
>= 0.0f
);
109 Source
->MaxDistance
= *values
;
110 Source
->NeedsUpdate
= AL_TRUE
;
113 case AL_ROLLOFF_FACTOR
:
114 CHECKVAL(*values
>= 0.0f
);
116 Source
->RollOffFactor
= *values
;
117 Source
->NeedsUpdate
= AL_TRUE
;
120 case AL_REFERENCE_DISTANCE
:
121 CHECKVAL(*values
>= 0.0f
);
123 Source
->RefDistance
= *values
;
124 Source
->NeedsUpdate
= AL_TRUE
;
128 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
130 Source
->MinGain
= *values
;
131 Source
->NeedsUpdate
= AL_TRUE
;
135 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
137 Source
->MaxGain
= *values
;
138 Source
->NeedsUpdate
= AL_TRUE
;
141 case AL_CONE_OUTER_GAIN
:
142 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
144 Source
->OuterGain
= *values
;
145 Source
->NeedsUpdate
= AL_TRUE
;
148 case AL_CONE_OUTER_GAINHF
:
149 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
151 Source
->OuterGainHF
= *values
;
152 Source
->NeedsUpdate
= AL_TRUE
;
155 case AL_AIR_ABSORPTION_FACTOR
:
156 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
158 Source
->AirAbsorptionFactor
= *values
;
159 Source
->NeedsUpdate
= AL_TRUE
;
162 case AL_ROOM_ROLLOFF_FACTOR
:
163 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
165 Source
->RoomRolloffFactor
= *values
;
166 Source
->NeedsUpdate
= AL_TRUE
;
169 case AL_DOPPLER_FACTOR
:
170 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
172 Source
->DopplerFactor
= *values
;
173 Source
->NeedsUpdate
= AL_TRUE
;
177 case AL_SAMPLE_OFFSET
:
179 CHECKVAL(*values
>= 0.0f
);
181 LockContext(Context
);
182 Source
->OffsetType
= name
;
183 Source
->Offset
= *values
;
185 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
186 !Context
->DeferUpdates
)
188 if(ApplyOffset(Source
) == AL_FALSE
)
190 UnlockContext(Context
);
191 RETERR(AL_INVALID_VALUE
);
194 UnlockContext(Context
);
199 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
201 LockContext(Context
);
202 Source
->Position
[0] = values
[0];
203 Source
->Position
[1] = values
[1];
204 Source
->Position
[2] = values
[2];
205 UnlockContext(Context
);
206 Source
->NeedsUpdate
= AL_TRUE
;
210 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
212 LockContext(Context
);
213 Source
->Velocity
[0] = values
[0];
214 Source
->Velocity
[1] = values
[1];
215 Source
->Velocity
[2] = values
[2];
216 UnlockContext(Context
);
217 Source
->NeedsUpdate
= AL_TRUE
;
221 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
223 LockContext(Context
);
224 Source
->Orientation
[0] = values
[0];
225 Source
->Orientation
[1] = values
[1];
226 Source
->Orientation
[2] = values
[2];
227 UnlockContext(Context
);
228 Source
->NeedsUpdate
= AL_TRUE
;
233 RETERR(AL_INVALID_ENUM
);
239 static ALenum
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALint
*values
)
241 ALCdevice
*device
= Context
->Device
;
242 ALbuffer
*buffer
= NULL
;
243 ALfilter
*filter
= NULL
;
244 ALeffectslot
*slot
= NULL
;
245 ALbufferlistitem
*oldlist
;
251 case AL_SOURCE_RELATIVE
:
252 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
254 Source
->HeadRelative
= (ALboolean
)*values
;
255 Source
->NeedsUpdate
= AL_TRUE
;
259 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
261 Source
->Looping
= (ALboolean
)*values
;
265 CHECKVAL(*values
== 0 || (buffer
=LookupBuffer(device
, *values
)) != NULL
);
267 LockContext(Context
);
268 if(!(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
))
270 UnlockContext(Context
);
271 RETERR(AL_INVALID_OPERATION
);
274 Source
->BuffersInQueue
= 0;
275 Source
->BuffersPlayed
= 0;
279 ALbufferlistitem
*BufferListItem
;
281 /* Source is now Static */
282 Source
->SourceType
= AL_STATIC
;
284 /* Add the selected buffer to a one-item queue */
285 BufferListItem
= malloc(sizeof(ALbufferlistitem
));
286 BufferListItem
->buffer
= buffer
;
287 BufferListItem
->next
= NULL
;
288 BufferListItem
->prev
= NULL
;
289 IncrementRef(&buffer
->ref
);
291 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, BufferListItem
);
292 Source
->BuffersInQueue
= 1;
294 ReadLock(&buffer
->lock
);
295 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
296 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
297 ReadUnlock(&buffer
->lock
);
298 if(buffer
->FmtChannels
== FmtMono
)
299 Source
->Update
= CalcSourceParams
;
301 Source
->Update
= CalcNonAttnSourceParams
;
302 Source
->NeedsUpdate
= AL_TRUE
;
306 /* Source is now Undetermined */
307 Source
->SourceType
= AL_UNDETERMINED
;
308 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, NULL
);
311 /* Delete all elements in the previous queue */
312 while(oldlist
!= NULL
)
314 ALbufferlistitem
*temp
= oldlist
;
315 oldlist
= temp
->next
;
318 DecrementRef(&temp
->buffer
->ref
);
321 UnlockContext(Context
);
324 case AL_SOURCE_STATE
:
326 RETERR(AL_INVALID_OPERATION
);
329 case AL_SAMPLE_OFFSET
:
331 CHECKVAL(*values
>= 0);
333 LockContext(Context
);
334 Source
->OffsetType
= name
;
335 Source
->Offset
= *values
;
337 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
338 !Context
->DeferUpdates
)
340 if(ApplyOffset(Source
) == AL_FALSE
)
342 UnlockContext(Context
);
343 RETERR(AL_INVALID_VALUE
);
346 UnlockContext(Context
);
349 case AL_DIRECT_FILTER
:
350 CHECKVAL(*values
== 0 || (filter
=LookupFilter(device
, *values
)) != NULL
);
352 LockContext(Context
);
355 Source
->DirectGain
= 1.0f
;
356 Source
->DirectGainHF
= 1.0f
;
360 Source
->DirectGain
= filter
->Gain
;
361 Source
->DirectGainHF
= filter
->GainHF
;
363 UnlockContext(Context
);
364 Source
->NeedsUpdate
= AL_TRUE
;
367 case AL_DIRECT_FILTER_GAINHF_AUTO
:
368 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
370 Source
->DryGainHFAuto
= *values
;
371 Source
->NeedsUpdate
= AL_TRUE
;
374 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
375 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
377 Source
->WetGainAuto
= *values
;
378 Source
->NeedsUpdate
= AL_TRUE
;
381 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
382 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
384 Source
->WetGainHFAuto
= *values
;
385 Source
->NeedsUpdate
= AL_TRUE
;
388 case AL_DIRECT_CHANNELS_SOFT
:
389 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
391 Source
->DirectChannels
= *values
;
392 Source
->NeedsUpdate
= AL_TRUE
;
395 case AL_DISTANCE_MODEL
:
396 CHECKVAL(*values
== AL_NONE
||
397 *values
== AL_INVERSE_DISTANCE
||
398 *values
== AL_INVERSE_DISTANCE_CLAMPED
||
399 *values
== AL_LINEAR_DISTANCE
||
400 *values
== AL_LINEAR_DISTANCE_CLAMPED
||
401 *values
== AL_EXPONENT_DISTANCE
||
402 *values
== AL_EXPONENT_DISTANCE_CLAMPED
);
404 Source
->DistanceModel
= *values
;
405 if(Context
->SourceDistanceModel
)
406 Source
->NeedsUpdate
= AL_TRUE
;
410 case AL_AUXILIARY_SEND_FILTER
:
411 LockContext(Context
);
412 if(!((ALuint
)values
[1] < device
->NumAuxSends
&&
413 (values
[0] == 0 || (slot
=LookupEffectSlot(Context
, values
[0])) != NULL
) &&
414 (values
[2] == 0 || (filter
=LookupFilter(device
, values
[2])) != NULL
)))
416 UnlockContext(Context
);
417 RETERR(AL_INVALID_VALUE
);
420 /* Add refcount on the new slot, and release the previous slot */
421 if(slot
) IncrementRef(&slot
->ref
);
422 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[values
[1]].Slot
, slot
);
423 if(slot
) DecrementRef(&slot
->ref
);
428 Source
->Send
[values
[1]].Gain
= 1.0f
;
429 Source
->Send
[values
[1]].GainHF
= 1.0f
;
433 Source
->Send
[values
[1]].Gain
= filter
->Gain
;
434 Source
->Send
[values
[1]].GainHF
= filter
->GainHF
;
436 Source
->NeedsUpdate
= AL_TRUE
;
437 UnlockContext(Context
);
441 case AL_MAX_DISTANCE
:
442 case AL_ROLLOFF_FACTOR
:
443 case AL_CONE_INNER_ANGLE
:
444 case AL_CONE_OUTER_ANGLE
:
445 case AL_REFERENCE_DISTANCE
:
446 fvals
[0] = (ALfloat
)*values
;
447 if((err
=SetSourcefv(Source
, Context
, name
, fvals
)) != AL_NO_ERROR
)
454 fvals
[0] = (ALfloat
)values
[0];
455 fvals
[1] = (ALfloat
)values
[1];
456 fvals
[2] = (ALfloat
)values
[2];
457 if((err
=SetSourcefv(Source
, Context
, name
, fvals
)) != AL_NO_ERROR
)
462 return AL_INVALID_ENUM
;
471 static ALenum
GetSourcedv(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALdouble
*values
)
480 case AL_MAX_DISTANCE
:
481 *values
= Source
->MaxDistance
;
484 case AL_ROLLOFF_FACTOR
:
485 *values
= Source
->RollOffFactor
;
488 case AL_REFERENCE_DISTANCE
:
489 *values
= Source
->RefDistance
;
492 case AL_CONE_INNER_ANGLE
:
493 *values
= Source
->InnerAngle
;
496 case AL_CONE_OUTER_ANGLE
:
497 *values
= Source
->OuterAngle
;
501 case AL_SAMPLE_OFFSET
:
503 LockContext(Context
);
504 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
505 Context
->Device
->Frequency
;
506 GetSourceOffsets(Source
, name
, offsets
, updateLen
);
507 UnlockContext(Context
);
508 *values
= offsets
[0];
511 case AL_CONE_OUTER_GAINHF
:
512 *values
= Source
->OuterGainHF
;
515 case AL_AIR_ABSORPTION_FACTOR
:
516 *values
= Source
->AirAbsorptionFactor
;
519 case AL_ROOM_ROLLOFF_FACTOR
:
520 *values
= Source
->RoomRolloffFactor
;
523 case AL_DOPPLER_FACTOR
:
524 *values
= Source
->DopplerFactor
;
527 case AL_SAMPLE_RW_OFFSETS_SOFT
:
528 case AL_BYTE_RW_OFFSETS_SOFT
:
529 LockContext(Context
);
530 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
531 Context
->Device
->Frequency
;
532 GetSourceOffsets(Source
, name
, values
, updateLen
);
533 UnlockContext(Context
);
536 case AL_SEC_OFFSET_LATENCY_SOFT
:
537 LockContext(Context
);
538 values
[0] = GetSourceSecOffset(Source
);
539 values
[1] = (ALdouble
)ALCdevice_GetLatency(Context
->Device
) /
541 UnlockContext(Context
);
545 LockContext(Context
);
546 values
[0] = Source
->Position
[0];
547 values
[1] = Source
->Position
[1];
548 values
[2] = Source
->Position
[2];
549 UnlockContext(Context
);
553 LockContext(Context
);
554 values
[0] = Source
->Velocity
[0];
555 values
[1] = Source
->Velocity
[1];
556 values
[2] = Source
->Velocity
[2];
557 UnlockContext(Context
);
561 LockContext(Context
);
562 values
[0] = Source
->Orientation
[0];
563 values
[1] = Source
->Orientation
[1];
564 values
[2] = Source
->Orientation
[2];
565 UnlockContext(Context
);
568 case AL_SOURCE_RELATIVE
:
571 case AL_SOURCE_STATE
:
572 case AL_BUFFERS_QUEUED
:
573 case AL_BUFFERS_PROCESSED
:
575 case AL_DIRECT_FILTER_GAINHF_AUTO
:
576 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
577 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
578 case AL_DIRECT_CHANNELS_SOFT
:
579 case AL_DISTANCE_MODEL
:
580 if((err
=GetSourceiv(Source
, Context
, name
, ivals
)) != AL_NO_ERROR
)
582 *values
= (ALdouble
)ivals
[0];
586 RETERR(AL_INVALID_ENUM
);
592 static ALenum
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint
*values
)
594 ALbufferlistitem
*BufferList
;
600 case AL_SOURCE_RELATIVE
:
601 *values
= Source
->HeadRelative
;
605 *values
= Source
->Looping
;
609 LockContext(Context
);
610 BufferList
= Source
->queue
;
611 if(Source
->SourceType
!= AL_STATIC
)
613 ALuint i
= Source
->BuffersPlayed
;
616 BufferList
= BufferList
->next
;
620 *values
= ((BufferList
&& BufferList
->buffer
) ?
621 BufferList
->buffer
->id
: 0);
622 UnlockContext(Context
);
625 case AL_SOURCE_STATE
:
626 *values
= Source
->state
;
629 case AL_BUFFERS_QUEUED
:
630 *values
= Source
->BuffersInQueue
;
633 case AL_BUFFERS_PROCESSED
:
634 LockContext(Context
);
635 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
637 /* Buffers on a looping source are in a perpetual state of
638 * PENDING, so don't report any as PROCESSED */
642 *values
= Source
->BuffersPlayed
;
643 UnlockContext(Context
);
647 *values
= Source
->SourceType
;
650 case AL_DIRECT_FILTER_GAINHF_AUTO
:
651 *values
= Source
->DryGainHFAuto
;
654 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
655 *values
= Source
->WetGainAuto
;
658 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
659 *values
= Source
->WetGainHFAuto
;
662 case AL_DIRECT_CHANNELS_SOFT
:
663 *values
= Source
->DirectChannels
;
666 case AL_DISTANCE_MODEL
:
667 *values
= Source
->DistanceModel
;
670 case AL_MAX_DISTANCE
:
671 case AL_ROLLOFF_FACTOR
:
672 case AL_REFERENCE_DISTANCE
:
673 case AL_CONE_INNER_ANGLE
:
674 case AL_CONE_OUTER_ANGLE
:
676 case AL_SAMPLE_OFFSET
:
678 case AL_DOPPLER_FACTOR
:
679 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
681 *values
= (ALint
)dvals
[0];
684 case AL_SAMPLE_RW_OFFSETS_SOFT
:
685 case AL_BYTE_RW_OFFSETS_SOFT
:
686 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
688 values
[0] = (ALint
)dvals
[0];
689 values
[1] = (ALint
)dvals
[0];
695 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
697 values
[0] = (ALint
)dvals
[0];
698 values
[1] = (ALint
)dvals
[1];
699 values
[2] = (ALint
)dvals
[2];
703 RETERR(AL_INVALID_ENUM
);
709 static ALenum
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint64
*values
)
717 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
718 LockContext(Context
);
719 values
[0] = GetSourceOffset(Source
);
720 values
[1] = ALCdevice_GetLatency(Context
->Device
);
721 UnlockContext(Context
);
724 case AL_MAX_DISTANCE
:
725 case AL_ROLLOFF_FACTOR
:
726 case AL_REFERENCE_DISTANCE
:
727 case AL_CONE_INNER_ANGLE
:
728 case AL_CONE_OUTER_ANGLE
:
730 case AL_SAMPLE_OFFSET
:
732 case AL_DOPPLER_FACTOR
:
733 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
735 *values
= (ALint64
)dvals
[0];
738 case AL_SAMPLE_RW_OFFSETS_SOFT
:
739 case AL_BYTE_RW_OFFSETS_SOFT
:
740 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
742 values
[0] = (ALint64
)dvals
[0];
743 values
[1] = (ALint64
)dvals
[0];
749 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
751 values
[0] = (ALint64
)dvals
[0];
752 values
[1] = (ALint64
)dvals
[1];
753 values
[2] = (ALint64
)dvals
[2];
756 case AL_SOURCE_RELATIVE
:
759 case AL_SOURCE_STATE
:
760 case AL_BUFFERS_QUEUED
:
761 case AL_BUFFERS_PROCESSED
:
763 case AL_DIRECT_FILTER_GAINHF_AUTO
:
764 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
765 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
766 case AL_DIRECT_CHANNELS_SOFT
:
767 case AL_DISTANCE_MODEL
:
768 if((err
=GetSourceiv(Source
, Context
, name
, ivals
)) != AL_NO_ERROR
)
774 RETERR(AL_INVALID_ENUM
);
783 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
, ALuint
*sources
)
788 Context
= GetContextRef();
795 CHECK_VALUE(Context
, n
>= 0);
796 for(cur
= 0;cur
< n
;cur
++)
798 ALsource
*source
= al_calloc(16, sizeof(ALsource
));
800 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
801 InitSourceParams(source
);
803 err
= NewThunkEntry(&source
->id
);
804 if(err
== AL_NO_ERROR
)
805 err
= InsertUIntMapEntry(&Context
->SourceMap
, source
->id
, source
);
806 if(err
!= AL_NO_ERROR
)
808 FreeThunkEntry(source
->id
);
809 memset(source
, 0, sizeof(ALsource
));
812 al_throwerr(Context
, err
);
815 sources
[cur
] = source
->id
;
821 alDeleteSources(cur
, sources
);
825 ALCcontext_DecRef(Context
);
829 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
833 Context
= GetContextRef();
838 ALbufferlistitem
*BufferList
;
842 CHECK_VALUE(Context
, n
>= 0);
844 /* Check that all Sources are valid */
847 if(LookupSource(Context
, sources
[i
]) == NULL
)
848 al_throwerr(Context
, AL_INVALID_NAME
);
853 ALsource
**srclist
, **srclistend
;
855 if((Source
=RemoveSource(Context
, sources
[i
])) == NULL
)
857 FreeThunkEntry(Source
->id
);
859 LockContext(Context
);
860 srclist
= Context
->ActiveSources
;
861 srclistend
= srclist
+ Context
->ActiveSourceCount
;
862 while(srclist
!= srclistend
)
864 if(*srclist
== Source
)
866 Context
->ActiveSourceCount
--;
867 *srclist
= *(--srclistend
);
872 UnlockContext(Context
);
874 while(Source
->queue
!= NULL
)
876 BufferList
= Source
->queue
;
877 Source
->queue
= BufferList
->next
;
879 if(BufferList
->buffer
!= NULL
)
880 DecrementRef(&BufferList
->buffer
->ref
);
884 for(j
= 0;j
< MAX_SENDS
;++j
)
886 if(Source
->Send
[j
].Slot
)
887 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
888 Source
->Send
[j
].Slot
= NULL
;
891 memset(Source
, 0, sizeof(*Source
));
897 ALCcontext_DecRef(Context
);
901 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
906 Context
= GetContextRef();
907 if(!Context
) return AL_FALSE
;
909 result
= (LookupSource(Context
, source
) ? AL_TRUE
: AL_FALSE
);
911 ALCcontext_DecRef(Context
);
917 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
922 Context
= GetContextRef();
925 if((Source
=LookupSource(Context
, source
)) == NULL
)
926 alSetError(Context
, AL_INVALID_NAME
);
930 case AL_CONE_INNER_ANGLE
:
931 case AL_CONE_OUTER_ANGLE
:
933 case AL_MAX_DISTANCE
:
934 case AL_ROLLOFF_FACTOR
:
935 case AL_REFERENCE_DISTANCE
:
938 case AL_CONE_OUTER_GAIN
:
939 case AL_CONE_OUTER_GAINHF
:
940 case AL_AIR_ABSORPTION_FACTOR
:
941 case AL_ROOM_ROLLOFF_FACTOR
:
942 case AL_DOPPLER_FACTOR
:
944 case AL_SAMPLE_OFFSET
:
946 SetSourcefv(Source
, Context
, param
, &value
);
950 alSetError(Context
, AL_INVALID_ENUM
);
953 ALCcontext_DecRef(Context
);
957 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
963 Context
= GetContextRef();
966 if((Source
=LookupSource(Context
, source
)) == NULL
)
967 alSetError(Context
, AL_INVALID_NAME
);
976 SetSourcefv(Source
, Context
, param
, fvals
);
980 alSetError(Context
, AL_INVALID_ENUM
);
983 ALCcontext_DecRef(Context
);
987 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
992 Context
= GetContextRef();
995 if((Source
=LookupSource(Context
, source
)) == NULL
)
996 alSetError(Context
, AL_INVALID_NAME
);
998 alSetError(Context
, AL_INVALID_VALUE
);
1002 case AL_CONE_INNER_ANGLE
:
1003 case AL_CONE_OUTER_ANGLE
:
1005 case AL_MAX_DISTANCE
:
1006 case AL_ROLLOFF_FACTOR
:
1007 case AL_REFERENCE_DISTANCE
:
1010 case AL_CONE_OUTER_GAIN
:
1011 case AL_CONE_OUTER_GAINHF
:
1013 case AL_SAMPLE_OFFSET
:
1014 case AL_BYTE_OFFSET
:
1015 case AL_AIR_ABSORPTION_FACTOR
:
1016 case AL_ROOM_ROLLOFF_FACTOR
:
1021 SetSourcefv(Source
, Context
, param
, values
);
1025 alSetError(Context
, AL_INVALID_ENUM
);
1028 ALCcontext_DecRef(Context
);
1032 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
1034 ALCcontext
*Context
;
1037 Context
= GetContextRef();
1038 if(!Context
) return;
1040 if((Source
=LookupSource(Context
, source
)) == NULL
)
1041 alSetError(Context
, AL_INVALID_NAME
);
1044 case AL_MAX_DISTANCE
:
1045 case AL_ROLLOFF_FACTOR
:
1046 case AL_CONE_INNER_ANGLE
:
1047 case AL_CONE_OUTER_ANGLE
:
1048 case AL_REFERENCE_DISTANCE
:
1049 case AL_SOURCE_RELATIVE
:
1052 case AL_SOURCE_STATE
:
1054 case AL_SAMPLE_OFFSET
:
1055 case AL_BYTE_OFFSET
:
1056 case AL_DIRECT_FILTER
:
1057 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1058 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1059 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1060 case AL_DIRECT_CHANNELS_SOFT
:
1061 case AL_DISTANCE_MODEL
:
1062 SetSourceiv(Source
, Context
, param
, &value
);
1066 alSetError(Context
, AL_INVALID_ENUM
);
1069 ALCcontext_DecRef(Context
);
1073 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
1075 ALCcontext
*Context
;
1079 Context
= GetContextRef();
1080 if(!Context
) return;
1082 if((Source
=LookupSource(Context
, source
)) == NULL
)
1083 alSetError(Context
, AL_INVALID_NAME
);
1089 case AL_AUXILIARY_SEND_FILTER
:
1093 SetSourceiv(Source
, Context
, param
, ivals
);
1097 alSetError(Context
, AL_INVALID_ENUM
);
1100 ALCcontext_DecRef(Context
);
1104 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
1106 ALCcontext
*Context
;
1109 Context
= GetContextRef();
1110 if(!Context
) return;
1112 if((Source
=LookupSource(Context
, source
)) == NULL
)
1113 alSetError(Context
, AL_INVALID_NAME
);
1115 alSetError(Context
, AL_INVALID_VALUE
);
1118 case AL_SOURCE_RELATIVE
:
1119 case AL_CONE_INNER_ANGLE
:
1120 case AL_CONE_OUTER_ANGLE
:
1123 case AL_SOURCE_STATE
:
1125 case AL_SAMPLE_OFFSET
:
1126 case AL_BYTE_OFFSET
:
1127 case AL_MAX_DISTANCE
:
1128 case AL_ROLLOFF_FACTOR
:
1129 case AL_REFERENCE_DISTANCE
:
1130 case AL_DIRECT_FILTER
:
1131 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1132 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1133 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1134 case AL_DISTANCE_MODEL
:
1135 case AL_DIRECT_CHANNELS_SOFT
:
1140 case AL_AUXILIARY_SEND_FILTER
:
1141 SetSourceiv(Source
, Context
, param
, values
);
1145 alSetError(Context
, AL_INVALID_ENUM
);
1148 ALCcontext_DecRef(Context
);
1152 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
1154 ALCcontext
*Context
;
1158 Context
= GetContextRef();
1159 if(!Context
) return;
1161 if((Source
=LookupSource(Context
, source
)) == NULL
)
1162 alSetError(Context
, AL_INVALID_NAME
);
1164 alSetError(Context
, AL_INVALID_VALUE
);
1171 case AL_MAX_DISTANCE
:
1172 case AL_ROLLOFF_FACTOR
:
1173 case AL_CONE_OUTER_GAIN
:
1174 case AL_CONE_OUTER_GAINHF
:
1176 case AL_SAMPLE_OFFSET
:
1177 case AL_BYTE_OFFSET
:
1178 case AL_CONE_INNER_ANGLE
:
1179 case AL_CONE_OUTER_ANGLE
:
1180 case AL_REFERENCE_DISTANCE
:
1181 case AL_AIR_ABSORPTION_FACTOR
:
1182 case AL_ROOM_ROLLOFF_FACTOR
:
1183 case AL_DOPPLER_FACTOR
:
1184 if(GetSourcedv(Source
, Context
, param
, &dval
) == AL_NO_ERROR
)
1185 *value
= (ALfloat
)dval
;
1189 alSetError(Context
, AL_INVALID_ENUM
);
1192 ALCcontext_DecRef(Context
);
1196 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
1198 ALCcontext
*Context
;
1202 Context
= GetContextRef();
1203 if(!Context
) return;
1205 if((Source
=LookupSource(Context
, source
)) == NULL
)
1206 alSetError(Context
, AL_INVALID_NAME
);
1207 else if(!(value1
&& value2
&& value3
))
1208 alSetError(Context
, AL_INVALID_VALUE
);
1214 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1216 *value1
= (ALfloat
)dvals
[0];
1217 *value2
= (ALfloat
)dvals
[1];
1218 *value3
= (ALfloat
)dvals
[2];
1223 alSetError(Context
, AL_INVALID_ENUM
);
1226 ALCcontext_DecRef(Context
);
1230 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
1232 ALCcontext
*Context
;
1242 case AL_MAX_DISTANCE
:
1243 case AL_ROLLOFF_FACTOR
:
1244 case AL_DOPPLER_FACTOR
:
1245 case AL_CONE_OUTER_GAIN
:
1247 case AL_SAMPLE_OFFSET
:
1248 case AL_BYTE_OFFSET
:
1249 case AL_CONE_INNER_ANGLE
:
1250 case AL_CONE_OUTER_ANGLE
:
1251 case AL_REFERENCE_DISTANCE
:
1252 case AL_CONE_OUTER_GAINHF
:
1253 case AL_AIR_ABSORPTION_FACTOR
:
1254 case AL_ROOM_ROLLOFF_FACTOR
:
1255 alGetSourcef(source
, param
, values
);
1261 alGetSource3f(source
, param
, values
+0, values
+1, values
+2);
1265 Context
= GetContextRef();
1266 if(!Context
) return;
1268 if((Source
=LookupSource(Context
, source
)) == NULL
)
1269 alSetError(Context
, AL_INVALID_NAME
);
1271 alSetError(Context
, AL_INVALID_VALUE
);
1274 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1275 case AL_BYTE_RW_OFFSETS_SOFT
:
1276 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1278 values
[0] = (ALfloat
)dvals
[0];
1279 values
[1] = (ALfloat
)dvals
[1];
1284 alSetError(Context
, AL_INVALID_ENUM
);
1287 ALCcontext_DecRef(Context
);
1291 AL_API
void AL_APIENTRY
alGetSourcedSOFT(ALuint source
, ALenum param
, ALdouble
*value
)
1293 ALCcontext
*Context
;
1296 Context
= GetContextRef();
1297 if(!Context
) return;
1299 if((Source
=LookupSource(Context
, source
)) == NULL
)
1300 alSetError(Context
, AL_INVALID_NAME
);
1302 alSetError(Context
, AL_INVALID_VALUE
);
1309 case AL_MAX_DISTANCE
:
1310 case AL_ROLLOFF_FACTOR
:
1311 case AL_CONE_OUTER_GAIN
:
1312 case AL_CONE_OUTER_GAINHF
:
1314 case AL_SAMPLE_OFFSET
:
1315 case AL_BYTE_OFFSET
:
1316 case AL_CONE_INNER_ANGLE
:
1317 case AL_CONE_OUTER_ANGLE
:
1318 case AL_REFERENCE_DISTANCE
:
1319 case AL_AIR_ABSORPTION_FACTOR
:
1320 case AL_ROOM_ROLLOFF_FACTOR
:
1321 case AL_DOPPLER_FACTOR
:
1322 GetSourcedv(Source
, Context
, param
, value
);
1326 alSetError(Context
, AL_INVALID_ENUM
);
1329 ALCcontext_DecRef(Context
);
1332 AL_API
void AL_APIENTRY
alGetSource3dSOFT(ALuint source
, ALenum param
, ALdouble
*value1
, ALdouble
*value2
, ALdouble
*value3
)
1334 ALCcontext
*Context
;
1338 Context
= GetContextRef();
1339 if(!Context
) return;
1341 if((Source
=LookupSource(Context
, source
)) == NULL
)
1342 alSetError(Context
, AL_INVALID_NAME
);
1343 else if(!(value1
&& value2
&& value3
))
1344 alSetError(Context
, AL_INVALID_VALUE
);
1350 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1359 alSetError(Context
, AL_INVALID_ENUM
);
1362 ALCcontext_DecRef(Context
);
1365 AL_API
void AL_APIENTRY
alGetSourcedvSOFT(ALuint source
, ALenum param
, ALdouble
*values
)
1367 ALCcontext
*Context
;
1370 Context
= GetContextRef();
1371 if(!Context
) return;
1373 if((Source
=LookupSource(Context
, source
)) == NULL
)
1374 alSetError(Context
, AL_INVALID_NAME
);
1376 alSetError(Context
, AL_INVALID_VALUE
);
1383 case AL_MAX_DISTANCE
:
1384 case AL_ROLLOFF_FACTOR
:
1385 case AL_DOPPLER_FACTOR
:
1386 case AL_CONE_OUTER_GAIN
:
1388 case AL_SAMPLE_OFFSET
:
1389 case AL_BYTE_OFFSET
:
1390 case AL_CONE_INNER_ANGLE
:
1391 case AL_CONE_OUTER_ANGLE
:
1392 case AL_REFERENCE_DISTANCE
:
1393 case AL_CONE_OUTER_GAINHF
:
1394 case AL_AIR_ABSORPTION_FACTOR
:
1395 case AL_ROOM_ROLLOFF_FACTOR
:
1397 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1398 case AL_BYTE_RW_OFFSETS_SOFT
:
1399 case AL_SEC_OFFSET_LATENCY_SOFT
:
1404 GetSourcedv(Source
, Context
, param
, values
);
1408 alSetError(Context
, AL_INVALID_ENUM
);
1411 ALCcontext_DecRef(Context
);
1415 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
1417 ALCcontext
*Context
;
1420 Context
= GetContextRef();
1421 if(!Context
) return;
1423 if((Source
=LookupSource(Context
, source
)) == NULL
)
1424 alSetError(Context
, AL_INVALID_NAME
);
1426 alSetError(Context
, AL_INVALID_VALUE
);
1429 case AL_MAX_DISTANCE
:
1430 case AL_ROLLOFF_FACTOR
:
1431 case AL_REFERENCE_DISTANCE
:
1432 case AL_SOURCE_RELATIVE
:
1433 case AL_CONE_INNER_ANGLE
:
1434 case AL_CONE_OUTER_ANGLE
:
1437 case AL_SOURCE_STATE
:
1438 case AL_BUFFERS_QUEUED
:
1439 case AL_BUFFERS_PROCESSED
:
1440 case AL_SOURCE_TYPE
:
1442 case AL_SAMPLE_OFFSET
:
1443 case AL_BYTE_OFFSET
:
1444 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1445 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1446 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1447 case AL_DOPPLER_FACTOR
:
1448 case AL_DIRECT_CHANNELS_SOFT
:
1449 case AL_DISTANCE_MODEL
:
1450 GetSourceiv(Source
, Context
, param
, value
);
1454 alSetError(Context
, AL_INVALID_ENUM
);
1457 ALCcontext_DecRef(Context
);
1461 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
1463 ALCcontext
*Context
;
1467 Context
= GetContextRef();
1468 if(!Context
) return;
1470 if((Source
=LookupSource(Context
, source
)) == NULL
)
1471 alSetError(Context
, AL_INVALID_NAME
);
1472 else if(!(value1
&& value2
&& value3
))
1473 alSetError(Context
, AL_INVALID_VALUE
);
1479 if(GetSourceiv(Source
, Context
, param
, ivals
) == AL_NO_ERROR
)
1488 alSetError(Context
, AL_INVALID_ENUM
);
1491 ALCcontext_DecRef(Context
);
1495 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
1497 ALCcontext
*Context
;
1500 Context
= GetContextRef();
1501 if(!Context
) return;
1503 if((Source
=LookupSource(Context
, source
)) == NULL
)
1504 alSetError(Context
, AL_INVALID_NAME
);
1506 alSetError(Context
, AL_INVALID_VALUE
);
1509 case AL_SOURCE_RELATIVE
:
1510 case AL_CONE_INNER_ANGLE
:
1511 case AL_CONE_OUTER_ANGLE
:
1514 case AL_SOURCE_STATE
:
1515 case AL_BUFFERS_QUEUED
:
1516 case AL_BUFFERS_PROCESSED
:
1518 case AL_SAMPLE_OFFSET
:
1519 case AL_BYTE_OFFSET
:
1520 case AL_MAX_DISTANCE
:
1521 case AL_ROLLOFF_FACTOR
:
1522 case AL_DOPPLER_FACTOR
:
1523 case AL_REFERENCE_DISTANCE
:
1524 case AL_SOURCE_TYPE
:
1525 case AL_DIRECT_FILTER
:
1526 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1527 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1528 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1529 case AL_DISTANCE_MODEL
:
1530 case AL_DIRECT_CHANNELS_SOFT
:
1532 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1533 case AL_BYTE_RW_OFFSETS_SOFT
:
1538 GetSourceiv(Source
, Context
, param
, values
);
1542 alSetError(Context
, AL_INVALID_ENUM
);
1545 ALCcontext_DecRef(Context
);
1549 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value
)
1551 ALCcontext
*Context
;
1554 Context
= GetContextRef();
1555 if(!Context
) return;
1557 if((Source
=LookupSource(Context
, source
)) == NULL
)
1558 alSetError(Context
, AL_INVALID_NAME
);
1560 alSetError(Context
, AL_INVALID_VALUE
);
1563 case AL_MAX_DISTANCE
:
1564 case AL_ROLLOFF_FACTOR
:
1565 case AL_REFERENCE_DISTANCE
:
1566 case AL_SOURCE_RELATIVE
:
1567 case AL_CONE_INNER_ANGLE
:
1568 case AL_CONE_OUTER_ANGLE
:
1571 case AL_SOURCE_STATE
:
1572 case AL_BUFFERS_QUEUED
:
1573 case AL_BUFFERS_PROCESSED
:
1574 case AL_SOURCE_TYPE
:
1576 case AL_SAMPLE_OFFSET
:
1577 case AL_BYTE_OFFSET
:
1578 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1579 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1580 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1581 case AL_DOPPLER_FACTOR
:
1582 case AL_DIRECT_CHANNELS_SOFT
:
1583 case AL_DISTANCE_MODEL
:
1584 GetSourcei64v(Source
, Context
, param
, value
);
1588 alSetError(Context
, AL_INVALID_ENUM
);
1591 ALCcontext_DecRef(Context
);
1594 AL_API
void AL_APIENTRY
alGetSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value1
, ALint64SOFT
*value2
, ALint64SOFT
*value3
)
1596 ALCcontext
*Context
;
1600 Context
= GetContextRef();
1601 if(!Context
) return;
1603 if((Source
=LookupSource(Context
, source
)) == NULL
)
1604 alSetError(Context
, AL_INVALID_NAME
);
1605 else if(!(value1
&& value2
&& value3
))
1606 alSetError(Context
, AL_INVALID_VALUE
);
1612 if(GetSourcei64v(Source
, Context
, param
, i64vals
) == AL_NO_ERROR
)
1614 *value1
= i64vals
[0];
1615 *value2
= i64vals
[1];
1616 *value3
= i64vals
[2];
1621 alSetError(Context
, AL_INVALID_ENUM
);
1624 ALCcontext_DecRef(Context
);
1627 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64SOFT
*values
)
1629 ALCcontext
*Context
;
1632 Context
= GetContextRef();
1633 if(!Context
) return;
1635 if((Source
=LookupSource(Context
, source
)) == NULL
)
1636 alSetError(Context
, AL_INVALID_NAME
);
1638 alSetError(Context
, AL_INVALID_VALUE
);
1641 case AL_MAX_DISTANCE
:
1642 case AL_ROLLOFF_FACTOR
:
1643 case AL_REFERENCE_DISTANCE
:
1644 case AL_SOURCE_RELATIVE
:
1645 case AL_CONE_INNER_ANGLE
:
1646 case AL_CONE_OUTER_ANGLE
:
1649 case AL_SOURCE_STATE
:
1650 case AL_BUFFERS_QUEUED
:
1651 case AL_BUFFERS_PROCESSED
:
1652 case AL_SOURCE_TYPE
:
1654 case AL_SAMPLE_OFFSET
:
1655 case AL_BYTE_OFFSET
:
1656 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1657 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1658 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1659 case AL_DOPPLER_FACTOR
:
1660 case AL_DIRECT_CHANNELS_SOFT
:
1661 case AL_DISTANCE_MODEL
:
1663 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1664 case AL_BYTE_RW_OFFSETS_SOFT
:
1665 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1670 GetSourcei64v(Source
, Context
, param
, values
);
1674 alSetError(Context
, AL_INVALID_ENUM
);
1677 ALCcontext_DecRef(Context
);
1681 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
1683 alSourcePlayv(1, &source
);
1685 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
1687 ALCcontext
*Context
;
1691 Context
= GetContextRef();
1692 if(!Context
) return;
1696 CHECK_VALUE(Context
, n
>= 0);
1697 for(i
= 0;i
< n
;i
++)
1699 if(!LookupSource(Context
, sources
[i
]))
1700 al_throwerr(Context
, AL_INVALID_NAME
);
1703 LockContext(Context
);
1704 while(Context
->MaxActiveSources
-Context
->ActiveSourceCount
< n
)
1709 newcount
= Context
->MaxActiveSources
<< 1;
1711 temp
= realloc(Context
->ActiveSources
,
1712 sizeof(*Context
->ActiveSources
) * newcount
);
1715 UnlockContext(Context
);
1716 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
1719 Context
->ActiveSources
= temp
;
1720 Context
->MaxActiveSources
= newcount
;
1723 for(i
= 0;i
< n
;i
++)
1725 Source
= LookupSource(Context
, sources
[i
]);
1726 if(Context
->DeferUpdates
) Source
->new_state
= AL_PLAYING
;
1727 else SetSourceState(Source
, Context
, AL_PLAYING
);
1729 UnlockContext(Context
);
1733 ALCcontext_DecRef(Context
);
1736 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
1738 alSourcePausev(1, &source
);
1740 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1742 ALCcontext
*Context
;
1746 Context
= GetContextRef();
1747 if(!Context
) return;
1751 CHECK_VALUE(Context
, n
>= 0);
1752 for(i
= 0;i
< n
;i
++)
1754 if(!LookupSource(Context
, sources
[i
]))
1755 al_throwerr(Context
, AL_INVALID_NAME
);
1758 LockContext(Context
);
1759 for(i
= 0;i
< n
;i
++)
1761 Source
= LookupSource(Context
, sources
[i
]);
1762 if(Context
->DeferUpdates
) Source
->new_state
= AL_PAUSED
;
1763 else SetSourceState(Source
, Context
, AL_PAUSED
);
1765 UnlockContext(Context
);
1769 ALCcontext_DecRef(Context
);
1772 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
1774 alSourceStopv(1, &source
);
1776 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1778 ALCcontext
*Context
;
1782 Context
= GetContextRef();
1783 if(!Context
) return;
1787 CHECK_VALUE(Context
, n
>= 0);
1788 for(i
= 0;i
< n
;i
++)
1790 if(!LookupSource(Context
, sources
[i
]))
1791 al_throwerr(Context
, AL_INVALID_NAME
);
1794 LockContext(Context
);
1795 for(i
= 0;i
< n
;i
++)
1797 Source
= LookupSource(Context
, sources
[i
]);
1798 Source
->new_state
= AL_NONE
;
1799 SetSourceState(Source
, Context
, AL_STOPPED
);
1801 UnlockContext(Context
);
1805 ALCcontext_DecRef(Context
);
1808 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
1810 alSourceRewindv(1, &source
);
1812 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1814 ALCcontext
*Context
;
1818 Context
= GetContextRef();
1819 if(!Context
) return;
1823 CHECK_VALUE(Context
, n
>= 0);
1824 for(i
= 0;i
< n
;i
++)
1826 if(!LookupSource(Context
, sources
[i
]))
1827 al_throwerr(Context
, AL_INVALID_NAME
);
1830 LockContext(Context
);
1831 for(i
= 0;i
< n
;i
++)
1833 Source
= LookupSource(Context
, sources
[i
]);
1834 Source
->new_state
= AL_NONE
;
1835 SetSourceState(Source
, Context
, AL_INITIAL
);
1837 UnlockContext(Context
);
1841 ALCcontext_DecRef(Context
);
1845 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint source
, ALsizei nb
, const ALuint
*buffers
)
1847 ALCcontext
*Context
;
1850 ALbufferlistitem
*BufferListStart
= NULL
;
1851 ALbufferlistitem
*BufferList
;
1852 ALbuffer
*BufferFmt
;
1857 Context
= GetContextRef();
1858 if(!Context
) return;
1862 ALCdevice
*device
= Context
->Device
;
1864 CHECK_VALUE(Context
, nb
>= 0);
1866 if((Source
=LookupSource(Context
, source
)) == NULL
)
1867 al_throwerr(Context
, AL_INVALID_NAME
);
1869 LockContext(Context
);
1870 if(Source
->SourceType
== AL_STATIC
)
1872 UnlockContext(Context
);
1873 /* Can't queue on a Static Source */
1874 al_throwerr(Context
, AL_INVALID_OPERATION
);
1879 /* Check for a valid Buffer, for its frequency and format */
1880 BufferList
= Source
->queue
;
1883 if(BufferList
->buffer
)
1885 BufferFmt
= BufferList
->buffer
;
1888 BufferList
= BufferList
->next
;
1891 for(i
= 0;i
< nb
;i
++)
1893 ALbuffer
*buffer
= NULL
;
1894 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
1896 UnlockContext(Context
);
1897 al_throwerr(Context
, AL_INVALID_NAME
);
1900 if(!BufferListStart
)
1902 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
1903 BufferListStart
->buffer
= buffer
;
1904 BufferListStart
->next
= NULL
;
1905 BufferListStart
->prev
= NULL
;
1906 BufferList
= BufferListStart
;
1910 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1911 BufferList
->next
->buffer
= buffer
;
1912 BufferList
->next
->next
= NULL
;
1913 BufferList
->next
->prev
= BufferList
;
1914 BufferList
= BufferList
->next
;
1916 if(!buffer
) continue;
1917 IncrementRef(&buffer
->ref
);
1919 ReadLock(&buffer
->lock
);
1920 if(BufferFmt
== NULL
)
1924 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
1925 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
1926 if(buffer
->FmtChannels
== FmtMono
)
1927 Source
->Update
= CalcSourceParams
;
1929 Source
->Update
= CalcNonAttnSourceParams
;
1931 Source
->NeedsUpdate
= AL_TRUE
;
1933 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
1934 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
1935 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
1937 ReadUnlock(&buffer
->lock
);
1938 UnlockContext(Context
);
1939 al_throwerr(Context
, AL_INVALID_OPERATION
);
1941 ReadUnlock(&buffer
->lock
);
1944 /* Source is now streaming */
1945 Source
->SourceType
= AL_STREAMING
;
1947 if(Source
->queue
== NULL
)
1948 Source
->queue
= BufferListStart
;
1951 /* Append to the end of the queue */
1952 BufferList
= Source
->queue
;
1953 while(BufferList
->next
!= NULL
)
1954 BufferList
= BufferList
->next
;
1956 BufferListStart
->prev
= BufferList
;
1957 BufferList
->next
= BufferListStart
;
1960 Source
->BuffersInQueue
+= nb
;
1962 UnlockContext(Context
);
1966 while(BufferListStart
)
1968 BufferList
= BufferListStart
;
1969 BufferListStart
= BufferList
->next
;
1971 if(BufferList
->buffer
)
1972 DecrementRef(&BufferList
->buffer
->ref
);
1978 ALCcontext_DecRef(Context
);
1981 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint source
, ALsizei nb
, ALuint
*buffers
)
1983 ALCcontext
*Context
;
1986 ALbufferlistitem
*BufferList
;
1991 Context
= GetContextRef();
1992 if(!Context
) return;
1996 CHECK_VALUE(Context
, nb
>= 0);
1998 if((Source
=LookupSource(Context
, source
)) == NULL
)
1999 al_throwerr(Context
, AL_INVALID_NAME
);
2001 LockContext(Context
);
2002 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
||
2003 (ALuint
)nb
> Source
->BuffersPlayed
)
2005 UnlockContext(Context
);
2006 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2007 al_throwerr(Context
, AL_INVALID_VALUE
);
2010 for(i
= 0;i
< nb
;i
++)
2012 BufferList
= Source
->queue
;
2013 Source
->queue
= BufferList
->next
;
2014 Source
->BuffersInQueue
--;
2015 Source
->BuffersPlayed
--;
2017 if(BufferList
->buffer
)
2019 buffers
[i
] = BufferList
->buffer
->id
;
2020 DecrementRef(&BufferList
->buffer
->ref
);
2028 Source
->queue
->prev
= NULL
;
2029 UnlockContext(Context
);
2033 ALCcontext_DecRef(Context
);
2037 static ALvoid
InitSourceParams(ALsource
*Source
)
2041 Source
->InnerAngle
= 360.0f
;
2042 Source
->OuterAngle
= 360.0f
;
2043 Source
->Pitch
= 1.0f
;
2044 Source
->Position
[0] = 0.0f
;
2045 Source
->Position
[1] = 0.0f
;
2046 Source
->Position
[2] = 0.0f
;
2047 Source
->Orientation
[0] = 0.0f
;
2048 Source
->Orientation
[1] = 0.0f
;
2049 Source
->Orientation
[2] = 0.0f
;
2050 Source
->Velocity
[0] = 0.0f
;
2051 Source
->Velocity
[1] = 0.0f
;
2052 Source
->Velocity
[2] = 0.0f
;
2053 Source
->RefDistance
= 1.0f
;
2054 Source
->MaxDistance
= FLT_MAX
;
2055 Source
->RollOffFactor
= 1.0f
;
2056 Source
->Looping
= AL_FALSE
;
2057 Source
->Gain
= 1.0f
;
2058 Source
->MinGain
= 0.0f
;
2059 Source
->MaxGain
= 1.0f
;
2060 Source
->OuterGain
= 0.0f
;
2061 Source
->OuterGainHF
= 1.0f
;
2063 Source
->DryGainHFAuto
= AL_TRUE
;
2064 Source
->WetGainAuto
= AL_TRUE
;
2065 Source
->WetGainHFAuto
= AL_TRUE
;
2066 Source
->AirAbsorptionFactor
= 0.0f
;
2067 Source
->RoomRolloffFactor
= 0.0f
;
2068 Source
->DopplerFactor
= 1.0f
;
2069 Source
->DirectChannels
= AL_FALSE
;
2071 Source
->DistanceModel
= DefaultDistanceModel
;
2073 Source
->Resampler
= DefaultResampler
;
2075 Source
->state
= AL_INITIAL
;
2076 Source
->new_state
= AL_NONE
;
2077 Source
->SourceType
= AL_UNDETERMINED
;
2078 Source
->Offset
= -1.0;
2080 Source
->DirectGain
= 1.0f
;
2081 Source
->DirectGainHF
= 1.0f
;
2082 for(i
= 0;i
< MAX_SENDS
;i
++)
2084 Source
->Send
[i
].Gain
= 1.0f
;
2085 Source
->Send
[i
].GainHF
= 1.0f
;
2088 Source
->NeedsUpdate
= AL_TRUE
;
2090 Source
->Hrtf
.Moving
= AL_FALSE
;
2091 Source
->Hrtf
.Counter
= 0;
2097 * Sets the source's new play state given its current state.
2099 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
2101 if(state
== AL_PLAYING
)
2103 ALbufferlistitem
*BufferList
;
2106 /* Check that there is a queue containing at least one valid, non zero
2108 BufferList
= Source
->queue
;
2111 if(BufferList
->buffer
!= NULL
&& BufferList
->buffer
->SampleLen
)
2113 BufferList
= BufferList
->next
;
2116 if(Source
->state
!= AL_PLAYING
)
2118 for(j
= 0;j
< MaxChannels
;j
++)
2120 for(k
= 0;k
< SRC_HISTORY_LENGTH
;k
++)
2121 Source
->Hrtf
.History
[j
][k
] = 0.0f
;
2122 for(k
= 0;k
< HRIR_LENGTH
;k
++)
2124 Source
->Hrtf
.Values
[j
][k
][0] = 0.0f
;
2125 Source
->Hrtf
.Values
[j
][k
][1] = 0.0f
;
2130 if(Source
->state
!= AL_PAUSED
)
2132 Source
->state
= AL_PLAYING
;
2133 Source
->position
= 0;
2134 Source
->position_fraction
= 0;
2135 Source
->BuffersPlayed
= 0;
2138 Source
->state
= AL_PLAYING
;
2140 // Check if an Offset has been set
2141 if(Source
->Offset
>= 0.0)
2142 ApplyOffset(Source
);
2144 /* If there's nothing to play, or device is disconnected, go right to
2146 if(!BufferList
|| !Context
->Device
->Connected
)
2148 SetSourceState(Source
, Context
, AL_STOPPED
);
2152 for(j
= 0;j
< Context
->ActiveSourceCount
;j
++)
2154 if(Context
->ActiveSources
[j
] == Source
)
2157 if(j
== Context
->ActiveSourceCount
)
2158 Context
->ActiveSources
[Context
->ActiveSourceCount
++] = Source
;
2160 else if(state
== AL_PAUSED
)
2162 if(Source
->state
== AL_PLAYING
)
2164 Source
->state
= AL_PAUSED
;
2165 Source
->Hrtf
.Moving
= AL_FALSE
;
2166 Source
->Hrtf
.Counter
= 0;
2169 else if(state
== AL_STOPPED
)
2171 if(Source
->state
!= AL_INITIAL
)
2173 Source
->state
= AL_STOPPED
;
2174 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
2175 Source
->Hrtf
.Moving
= AL_FALSE
;
2176 Source
->Hrtf
.Counter
= 0;
2178 Source
->Offset
= -1.0;
2180 else if(state
== AL_INITIAL
)
2182 if(Source
->state
!= AL_INITIAL
)
2184 Source
->state
= AL_INITIAL
;
2185 Source
->position
= 0;
2186 Source
->position_fraction
= 0;
2187 Source
->BuffersPlayed
= 0;
2188 Source
->Hrtf
.Moving
= AL_FALSE
;
2189 Source
->Hrtf
.Counter
= 0;
2191 Source
->Offset
= -1.0;
2197 * Gets the current read offset for the given Source, in 32.32 fixed-point
2198 * samples. The offset is relative to the start of the queue (not the start of
2199 * the current buffer).
2201 static ALint64
GetSourceOffset(const ALsource
*Source
)
2203 const ALbufferlistitem
*BufferList
;
2207 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2210 /* NOTE: This is the offset into the *current* buffer, so add the length of
2211 * any played buffers */
2212 readPos
= (ALuint64
)Source
->position
<< 32;
2213 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
2214 BufferList
= Source
->queue
;
2215 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2217 if(BufferList
->buffer
)
2218 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
2219 BufferList
= BufferList
->next
;
2222 return (ALint64
)minu64(readPos
, MAKEU64(0x7fffffff,0xffffffff));
2225 /* GetSourceSecOffset
2227 * Gets the current read offset for the given Source, in seconds. The offset is
2228 * relative to the start of the queue (not the start of the current buffer).
2230 static ALdouble
GetSourceSecOffset(const ALsource
*Source
)
2232 const ALbufferlistitem
*BufferList
;
2233 const ALbuffer
*Buffer
= NULL
;
2237 BufferList
= Source
->queue
;
2240 if(BufferList
->buffer
)
2242 Buffer
= BufferList
->buffer
;
2245 BufferList
= BufferList
->next
;
2248 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2251 /* NOTE: This is the offset into the *current* buffer, so add the length of
2252 * any played buffers */
2253 readPos
= (ALuint64
)Source
->position
<< FRACTIONBITS
;
2254 readPos
|= (ALuint64
)Source
->position_fraction
;
2255 BufferList
= Source
->queue
;
2256 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2258 if(BufferList
->buffer
)
2259 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< FRACTIONBITS
;
2260 BufferList
= BufferList
->next
;
2263 return (ALdouble
)readPos
/ (ALdouble
)FRACTIONONE
/ (ALdouble
)Buffer
->Frequency
;
2268 * Gets the current read and write offsets for the given Source, in the
2269 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2270 * the start of the queue (not the start of the current buffer).
2272 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
2274 const ALbufferlistitem
*BufferList
;
2275 const ALbuffer
*Buffer
= NULL
;
2276 ALuint readPos
, writePos
;
2277 ALuint totalBufferLen
;
2280 // Find the first valid Buffer in the Queue
2281 BufferList
= Source
->queue
;
2284 if(BufferList
->buffer
)
2286 Buffer
= BufferList
->buffer
;
2289 BufferList
= BufferList
->next
;
2292 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2299 if(updateLen
> 0.0 && updateLen
< 0.015)
2302 /* NOTE: This is the offset into the *current* buffer, so add the length of
2303 * any played buffers */
2304 readPos
= Source
->position
;
2306 BufferList
= Source
->queue
;
2307 for(i
= 0;BufferList
;i
++)
2309 if(BufferList
->buffer
)
2311 if(i
< Source
->BuffersPlayed
)
2312 readPos
+= BufferList
->buffer
->SampleLen
;
2313 totalBufferLen
+= BufferList
->buffer
->SampleLen
;
2315 BufferList
= BufferList
->next
;
2317 if(Source
->state
== AL_PLAYING
)
2318 writePos
= readPos
+ (ALuint
)(updateLen
*Buffer
->Frequency
);
2324 readPos
%= totalBufferLen
;
2325 writePos
%= totalBufferLen
;
2329 /* Wrap positions back to 0 */
2330 if(readPos
>= totalBufferLen
)
2332 if(writePos
>= totalBufferLen
)
2339 offset
[0] = (ALdouble
)readPos
/ Buffer
->Frequency
;
2340 offset
[1] = (ALdouble
)writePos
/ Buffer
->Frequency
;
2343 case AL_SAMPLE_OFFSET
:
2344 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2345 offset
[0] = (ALdouble
)readPos
;
2346 offset
[1] = (ALdouble
)writePos
;
2349 case AL_BYTE_OFFSET
:
2350 case AL_BYTE_RW_OFFSETS_SOFT
:
2351 if(Buffer
->OriginalType
== UserFmtIMA4
)
2353 ALuint BlockSize
= 36 * ChannelsFromFmt(Buffer
->FmtChannels
);
2354 ALuint FrameBlockSize
= 65;
2356 /* Round down to nearest ADPCM block */
2357 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2358 if(Source
->state
!= AL_PLAYING
)
2359 offset
[1] = offset
[0];
2362 /* Round up to nearest ADPCM block */
2363 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2364 FrameBlockSize
* BlockSize
);
2369 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2370 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2371 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2380 * Apply the stored playback offset to the Source. This function will update
2381 * the number of buffers "played" given the stored offset.
2383 ALboolean
ApplyOffset(ALsource
*Source
)
2385 const ALbufferlistitem
*BufferList
;
2386 const ALbuffer
*Buffer
;
2387 ALint bufferLen
, totalBufferLen
;
2388 ALint buffersPlayed
;
2391 /* Get sample frame offset */
2392 offset
= GetSampleOffset(Source
);
2399 BufferList
= Source
->queue
;
2402 Buffer
= BufferList
->buffer
;
2403 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2405 if(bufferLen
<= offset
-totalBufferLen
)
2407 /* Offset is past this buffer so increment to the next buffer */
2410 else if(totalBufferLen
<= offset
)
2412 /* Offset is in this buffer */
2413 Source
->BuffersPlayed
= buffersPlayed
;
2415 Source
->position
= offset
- totalBufferLen
;
2416 Source
->position_fraction
= 0;
2420 totalBufferLen
+= bufferLen
;
2422 BufferList
= BufferList
->next
;
2425 /* Offset is out of range of the queue */
2432 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2433 * Second offset supplied by the application). This takes into account the fact
2434 * that the buffer format may have been modifed since.
2436 static ALint
GetSampleOffset(ALsource
*Source
)
2438 const ALbuffer
*Buffer
= NULL
;
2439 const ALbufferlistitem
*BufferList
;
2442 /* Find the first valid Buffer in the Queue */
2443 BufferList
= Source
->queue
;
2446 if(BufferList
->buffer
)
2448 Buffer
= BufferList
->buffer
;
2451 BufferList
= BufferList
->next
;
2456 Source
->Offset
= -1.0;
2460 switch(Source
->OffsetType
)
2462 case AL_BYTE_OFFSET
:
2463 /* Determine the ByteOffset (and ensure it is block aligned) */
2464 Offset
= (ALint
)Source
->Offset
;
2465 if(Buffer
->OriginalType
== UserFmtIMA4
)
2467 Offset
/= 36 * ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2471 Offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2474 case AL_SAMPLE_OFFSET
:
2475 Offset
= (ALint
)Source
->Offset
;
2479 Offset
= (ALint
)(Source
->Offset
* Buffer
->Frequency
);
2482 Source
->Offset
= -1.0;
2490 * Destroys all sources in the source map.
2492 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2496 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2498 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2499 Context
->SourceMap
.array
[pos
].value
= NULL
;
2501 while(temp
->queue
!= NULL
)
2503 ALbufferlistitem
*BufferList
= temp
->queue
;
2504 temp
->queue
= BufferList
->next
;
2506 if(BufferList
->buffer
!= NULL
)
2507 DecrementRef(&BufferList
->buffer
->ref
);
2511 for(j
= 0;j
< MAX_SENDS
;++j
)
2513 if(temp
->Send
[j
].Slot
)
2514 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2515 temp
->Send
[j
].Slot
= NULL
;
2518 FreeThunkEntry(temp
->id
);
2519 memset(temp
, 0, sizeof(*temp
));