Protect alProcessUpdatesSOFT with a lock
[openal-soft.git] / OpenAL32 / alState.c
blobb4f17b9dfe8d362ca76e234ad9ad28afd612f412
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2000 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
21 #include "config.h"
23 #include <stdlib.h>
24 #include "alMain.h"
25 #include "AL/alc.h"
26 #include "AL/al.h"
27 #include "AL/alext.h"
28 #include "alError.h"
29 #include "alSource.h"
30 #include "alAuxEffectSlot.h"
31 #include "alMidi.h"
33 #include "midi/base.h"
36 static const ALchar alVendor[] = "OpenAL Community";
37 static const ALchar alVersion[] = "1.1 ALSOFT "ALSOFT_VERSION;
38 static const ALchar alRenderer[] = "OpenAL Soft";
40 // Error Messages
41 static const ALchar alNoError[] = "No Error";
42 static const ALchar alErrInvalidName[] = "Invalid Name";
43 static const ALchar alErrInvalidEnum[] = "Invalid Enum";
44 static const ALchar alErrInvalidValue[] = "Invalid Value";
45 static const ALchar alErrInvalidOp[] = "Invalid Operation";
46 static const ALchar alErrOutOfMemory[] = "Out of Memory";
48 AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
50 ALCcontext *context;
52 context = GetContextRef();
53 if(!context) return;
55 switch(capability)
57 case AL_SOURCE_DISTANCE_MODEL:
58 context->SourceDistanceModel = AL_TRUE;
59 ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
60 break;
62 default:
63 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
66 done:
67 ALCcontext_DecRef(context);
70 AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
72 ALCcontext *context;
74 context = GetContextRef();
75 if(!context) return;
77 switch(capability)
79 case AL_SOURCE_DISTANCE_MODEL:
80 context->SourceDistanceModel = AL_FALSE;
81 ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
82 break;
84 default:
85 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
88 done:
89 ALCcontext_DecRef(context);
92 AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
94 ALCcontext *context;
95 ALboolean value=AL_FALSE;
97 context = GetContextRef();
98 if(!context) return AL_FALSE;
100 switch(capability)
102 case AL_SOURCE_DISTANCE_MODEL:
103 value = context->SourceDistanceModel;
104 break;
106 default:
107 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
110 done:
111 ALCcontext_DecRef(context);
113 return value;
116 AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
118 ALCcontext *context;
119 ALboolean value=AL_FALSE;
121 context = GetContextRef();
122 if(!context) return AL_FALSE;
124 switch(pname)
126 case AL_DOPPLER_FACTOR:
127 if(context->DopplerFactor != 0.0f)
128 value = AL_TRUE;
129 break;
131 case AL_DOPPLER_VELOCITY:
132 if(context->DopplerVelocity != 0.0f)
133 value = AL_TRUE;
134 break;
136 case AL_DISTANCE_MODEL:
137 if(context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED)
138 value = AL_TRUE;
139 break;
141 case AL_SPEED_OF_SOUND:
142 if(context->SpeedOfSound != 0.0f)
143 value = AL_TRUE;
144 break;
146 case AL_DEFERRED_UPDATES_SOFT:
147 value = context->DeferUpdates;
148 break;
150 default:
151 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
154 done:
155 ALCcontext_DecRef(context);
157 return value;
160 AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
162 ALCdevice *device;
163 ALCcontext *context;
164 ALdouble value = 0.0;
166 context = GetContextRef();
167 if(!context) return 0.0;
169 switch(pname)
171 case AL_DOPPLER_FACTOR:
172 value = (ALdouble)context->DopplerFactor;
173 break;
175 case AL_DOPPLER_VELOCITY:
176 value = (ALdouble)context->DopplerVelocity;
177 break;
179 case AL_DISTANCE_MODEL:
180 value = (ALdouble)context->DistanceModel;
181 break;
183 case AL_SPEED_OF_SOUND:
184 value = (ALdouble)context->SpeedOfSound;
185 break;
187 case AL_DEFERRED_UPDATES_SOFT:
188 value = (ALdouble)context->DeferUpdates;
189 break;
191 case AL_MIDI_GAIN_SOFT:
192 device = context->Device;
193 value = (ALdouble)MidiSynth_getGain(device->Synth);
194 break;
196 case AL_MIDI_STATE_SOFT:
197 device = context->Device;
198 value = (ALdouble)MidiSynth_getState(device->Synth);
199 break;
201 default:
202 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
205 done:
206 ALCcontext_DecRef(context);
208 return value;
211 AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
213 ALCdevice *device;
214 ALCcontext *context;
215 ALfloat value = 0.0f;
217 context = GetContextRef();
218 if(!context) return 0.0f;
220 switch(pname)
222 case AL_DOPPLER_FACTOR:
223 value = context->DopplerFactor;
224 break;
226 case AL_DOPPLER_VELOCITY:
227 value = context->DopplerVelocity;
228 break;
230 case AL_DISTANCE_MODEL:
231 value = (ALfloat)context->DistanceModel;
232 break;
234 case AL_SPEED_OF_SOUND:
235 value = context->SpeedOfSound;
236 break;
238 case AL_DEFERRED_UPDATES_SOFT:
239 value = (ALfloat)context->DeferUpdates;
240 break;
242 case AL_MIDI_GAIN_SOFT:
243 device = context->Device;
244 value = MidiSynth_getGain(device->Synth);
245 break;
247 case AL_MIDI_STATE_SOFT:
248 device = context->Device;
249 value = (ALfloat)MidiSynth_getState(device->Synth);
250 break;
252 default:
253 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
256 done:
257 ALCcontext_DecRef(context);
259 return value;
262 AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
264 ALCcontext *context;
265 ALCdevice *device;
266 MidiSynth *synth;
267 ALint value = 0;
269 context = GetContextRef();
270 if(!context) return 0;
272 switch(pname)
274 case AL_DOPPLER_FACTOR:
275 value = (ALint)context->DopplerFactor;
276 break;
278 case AL_DOPPLER_VELOCITY:
279 value = (ALint)context->DopplerVelocity;
280 break;
282 case AL_DISTANCE_MODEL:
283 value = (ALint)context->DistanceModel;
284 break;
286 case AL_SPEED_OF_SOUND:
287 value = (ALint)context->SpeedOfSound;
288 break;
290 case AL_DEFERRED_UPDATES_SOFT:
291 value = (ALint)context->DeferUpdates;
292 break;
294 case AL_SOUNDFONTS_SIZE_SOFT:
295 device = context->Device;
296 synth = device->Synth;
297 value = synth->NumSoundfonts;
298 break;
300 case AL_MIDI_STATE_SOFT:
301 device = context->Device;
302 value = MidiSynth_getState(device->Synth);
303 break;
305 default:
306 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
309 done:
310 ALCcontext_DecRef(context);
312 return value;
315 AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
317 ALCcontext *context;
318 ALCdevice *device;
319 MidiSynth *synth;
320 ALint64SOFT value = 0;
322 context = GetContextRef();
323 if(!context) return 0;
325 switch(pname)
327 case AL_DOPPLER_FACTOR:
328 value = (ALint64SOFT)context->DopplerFactor;
329 break;
331 case AL_DOPPLER_VELOCITY:
332 value = (ALint64SOFT)context->DopplerVelocity;
333 break;
335 case AL_DISTANCE_MODEL:
336 value = (ALint64SOFT)context->DistanceModel;
337 break;
339 case AL_SPEED_OF_SOUND:
340 value = (ALint64SOFT)context->SpeedOfSound;
341 break;
343 case AL_DEFERRED_UPDATES_SOFT:
344 value = (ALint64SOFT)context->DeferUpdates;
345 break;
347 case AL_MIDI_CLOCK_SOFT:
348 device = context->Device;
349 ALCdevice_Lock(device);
350 value = MidiSynth_getTime(device->Synth);
351 ALCdevice_Unlock(device);
352 break;
354 case AL_SOUNDFONTS_SIZE_SOFT:
355 device = context->Device;
356 synth = device->Synth;
357 value = (ALint64SOFT)synth->NumSoundfonts;
358 break;
360 case AL_MIDI_STATE_SOFT:
361 device = context->Device;
362 value = (ALint64SOFT)MidiSynth_getState(device->Synth);
363 break;
365 default:
366 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
369 done:
370 ALCcontext_DecRef(context);
372 return value;
375 AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
377 ALCcontext *context;
379 if(values)
381 switch(pname)
383 case AL_DOPPLER_FACTOR:
384 case AL_DOPPLER_VELOCITY:
385 case AL_DISTANCE_MODEL:
386 case AL_SPEED_OF_SOUND:
387 case AL_DEFERRED_UPDATES_SOFT:
388 values[0] = alGetBoolean(pname);
389 return;
393 context = GetContextRef();
394 if(!context) return;
396 if(!(values))
397 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
398 switch(pname)
400 default:
401 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
404 done:
405 ALCcontext_DecRef(context);
408 AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
410 ALCcontext *context;
412 if(values)
414 switch(pname)
416 case AL_DOPPLER_FACTOR:
417 case AL_DOPPLER_VELOCITY:
418 case AL_DISTANCE_MODEL:
419 case AL_SPEED_OF_SOUND:
420 case AL_DEFERRED_UPDATES_SOFT:
421 case AL_MIDI_GAIN_SOFT:
422 case AL_MIDI_STATE_SOFT:
423 values[0] = alGetDouble(pname);
424 return;
428 context = GetContextRef();
429 if(!context) return;
431 if(!(values))
432 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
433 switch(pname)
435 default:
436 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
439 done:
440 ALCcontext_DecRef(context);
443 AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
445 ALCcontext *context;
447 if(values)
449 switch(pname)
451 case AL_DOPPLER_FACTOR:
452 case AL_DOPPLER_VELOCITY:
453 case AL_DISTANCE_MODEL:
454 case AL_SPEED_OF_SOUND:
455 case AL_DEFERRED_UPDATES_SOFT:
456 case AL_MIDI_GAIN_SOFT:
457 case AL_MIDI_STATE_SOFT:
458 values[0] = alGetFloat(pname);
459 return;
463 context = GetContextRef();
464 if(!context) return;
466 if(!(values))
467 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
468 switch(pname)
470 default:
471 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
474 done:
475 ALCcontext_DecRef(context);
478 AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
480 ALCcontext *context;
481 ALCdevice *device;
482 MidiSynth *synth;
483 ALsizei i;
485 if(values)
487 switch(pname)
489 case AL_DOPPLER_FACTOR:
490 case AL_DOPPLER_VELOCITY:
491 case AL_DISTANCE_MODEL:
492 case AL_SPEED_OF_SOUND:
493 case AL_DEFERRED_UPDATES_SOFT:
494 case AL_SOUNDFONTS_SIZE_SOFT:
495 case AL_MIDI_STATE_SOFT:
496 values[0] = alGetInteger(pname);
497 return;
501 context = GetContextRef();
502 if(!context) return;
504 switch(pname)
506 case AL_SOUNDFONTS_SOFT:
507 device = context->Device;
508 synth = device->Synth;
509 if(synth->NumSoundfonts > 0)
511 if(!(values))
512 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
513 for(i = 0;i < synth->NumSoundfonts;i++)
514 values[i] = synth->Soundfonts[i]->id;
516 break;
518 default:
519 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
522 done:
523 ALCcontext_DecRef(context);
526 AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
528 ALCcontext *context;
529 ALCdevice *device;
530 MidiSynth *synth;
531 ALsizei i;
533 if(values)
535 switch(pname)
537 case AL_DOPPLER_FACTOR:
538 case AL_DOPPLER_VELOCITY:
539 case AL_DISTANCE_MODEL:
540 case AL_SPEED_OF_SOUND:
541 case AL_DEFERRED_UPDATES_SOFT:
542 case AL_MIDI_CLOCK_SOFT:
543 case AL_SOUNDFONTS_SIZE_SOFT:
544 case AL_MIDI_STATE_SOFT:
545 values[0] = alGetInteger64SOFT(pname);
546 return;
550 context = GetContextRef();
551 if(!context) return;
553 switch(pname)
555 case AL_SOUNDFONTS_SOFT:
556 device = context->Device;
557 synth = device->Synth;
558 if(synth->NumSoundfonts > 0)
560 if(!(values))
561 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
562 for(i = 0;i < synth->NumSoundfonts;i++)
563 values[i] = (ALint64SOFT)synth->Soundfonts[i]->id;
565 break;
567 default:
568 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
571 done:
572 ALCcontext_DecRef(context);
575 AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
577 const ALchar *value = NULL;
578 ALCcontext *context;
580 context = GetContextRef();
581 if(!context) return NULL;
583 switch(pname)
585 case AL_VENDOR:
586 value = alVendor;
587 break;
589 case AL_VERSION:
590 value = alVersion;
591 break;
593 case AL_RENDERER:
594 value = alRenderer;
595 break;
597 case AL_EXTENSIONS:
598 value = context->ExtensionList;
599 break;
601 case AL_NO_ERROR:
602 value = alNoError;
603 break;
605 case AL_INVALID_NAME:
606 value = alErrInvalidName;
607 break;
609 case AL_INVALID_ENUM:
610 value = alErrInvalidEnum;
611 break;
613 case AL_INVALID_VALUE:
614 value = alErrInvalidValue;
615 break;
617 case AL_INVALID_OPERATION:
618 value = alErrInvalidOp;
619 break;
621 case AL_OUT_OF_MEMORY:
622 value = alErrOutOfMemory;
623 break;
625 default:
626 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
629 done:
630 ALCcontext_DecRef(context);
632 return value;
635 AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
637 ALCcontext *context;
639 context = GetContextRef();
640 if(!context) return;
642 if(!(value >= 0.0f && isfinite(value)))
643 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
645 context->DopplerFactor = value;
646 ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
648 done:
649 ALCcontext_DecRef(context);
652 AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
654 ALCcontext *context;
656 context = GetContextRef();
657 if(!context) return;
659 if(!(value >= 0.0f && isfinite(value)))
660 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
662 context->DopplerVelocity = value;
663 ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
665 done:
666 ALCcontext_DecRef(context);
669 AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value)
671 ALCcontext *context;
673 context = GetContextRef();
674 if(!context) return;
676 if(!(value > 0.0f && isfinite(value)))
677 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
679 context->SpeedOfSound = value;
680 ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
682 done:
683 ALCcontext_DecRef(context);
686 AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
688 ALCcontext *context;
690 context = GetContextRef();
691 if(!context) return;
693 if(!(value == AL_INVERSE_DISTANCE || value == AL_INVERSE_DISTANCE_CLAMPED ||
694 value == AL_LINEAR_DISTANCE || value == AL_LINEAR_DISTANCE_CLAMPED ||
695 value == AL_EXPONENT_DISTANCE || value == AL_EXPONENT_DISTANCE_CLAMPED ||
696 value == AL_NONE))
697 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
699 context->DistanceModel = value;
700 if(!context->SourceDistanceModel)
701 ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
703 done:
704 ALCcontext_DecRef(context);
708 AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void)
710 ALCcontext *context;
712 context = GetContextRef();
713 if(!context) return;
715 if(!context->DeferUpdates)
717 ALboolean UpdateSources;
718 ALvoice *voice, *voice_end;
719 ALeffectslot **slot, **slot_end;
720 FPUCtl oldMode;
722 SetMixerFPUMode(&oldMode);
724 LockContext(context);
725 context->DeferUpdates = AL_TRUE;
727 /* Make sure all pending updates are performed */
728 UpdateSources = ATOMIC_EXCHANGE(ALenum, &context->UpdateSources, AL_FALSE);
730 voice = context->Voices;
731 voice_end = voice + context->VoiceCount;
732 while(voice != voice_end)
734 ALsource *source = voice->Source;
735 if(!source) goto next;
737 if(source->state != AL_PLAYING && source->state != AL_PAUSED)
739 voice->Source = NULL;
740 continue;
743 if(ATOMIC_EXCHANGE(ALenum, &source->NeedsUpdate, AL_FALSE) || UpdateSources)
744 voice->Update(voice, source, context);
745 next:
746 voice++;
749 slot = VECTOR_ITER_BEGIN(context->ActiveAuxSlots);
750 slot_end = VECTOR_ITER_END(context->ActiveAuxSlots);
751 while(slot != slot_end)
753 if(ATOMIC_EXCHANGE(ALenum, &(*slot)->NeedsUpdate, AL_FALSE))
754 V((*slot)->EffectState,update)(context->Device, *slot);
755 slot++;
758 UnlockContext(context);
759 RestoreFPUMode(&oldMode);
762 ALCcontext_DecRef(context);
765 AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void)
767 ALCcontext *context;
769 context = GetContextRef();
770 if(!context) return;
772 LockContext(context);
773 if(ExchangeInt(&context->DeferUpdates, AL_FALSE))
775 ALsizei pos;
777 LockUIntMapRead(&context->SourceMap);
778 for(pos = 0;pos < context->SourceMap.size;pos++)
780 ALsource *Source = context->SourceMap.array[pos].value;
781 ALenum new_state;
783 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
784 Source->Offset >= 0.0)
786 ReadLock(&Source->queue_lock);
787 ApplyOffset(Source);
788 ReadUnlock(&Source->queue_lock);
791 new_state = ExchangeInt(&Source->new_state, AL_NONE);
792 if(new_state)
793 SetSourceState(Source, context, new_state);
795 UnlockUIntMapRead(&context->SourceMap);
797 UnlockContext(context);
799 ALCcontext_DecRef(context);