Make the fontsound's buffer and link fields atomic
[openal-soft.git] / OpenAL32 / alFontsound.c
blob069fedd3bc8fe6c66bb6eae0ed6c41f474698dbe
2 #include "config.h"
4 #include <stdlib.h>
5 #include <string.h>
7 #include "alMain.h"
8 #include "alMidi.h"
9 #include "alError.h"
10 #include "alThunk.h"
11 #include "alBuffer.h"
13 #include "midi/base.h"
16 extern inline struct ALfontsound *LookupFontsound(ALCdevice *device, ALuint id);
17 extern inline struct ALfontsound *RemoveFontsound(ALCdevice *device, ALuint id);
20 static void ALfontsound_Construct(ALfontsound *self);
21 static void ALfontsound_Destruct(ALfontsound *self);
22 void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, ALint value);
23 static ALsfmodulator *ALfontsound_getModStage(ALfontsound *self, ALsizei stage);
24 void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint value);
25 static void ALfontsound_getModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint *values);
27 static inline struct ALsfmodulator *LookupModulator(ALfontsound *sound, ALuint id)
29 ALsfmodulator *mod = LookupUIntMapKey(&sound->ModulatorMap, id>>2);
30 if(mod) mod += id&3;
31 return mod;
35 AL_API void AL_APIENTRY alGenFontsoundsSOFT(ALsizei n, ALuint *ids)
37 ALCcontext *context;
38 ALsizei cur = 0;
40 context = GetContextRef();
41 if(!context) return;
43 if(!(n >= 0))
44 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
46 for(cur = 0;cur < n;cur++)
48 ALfontsound *sound = NewFontsound(context);
49 if(!sound)
51 alDeleteFontsoundsSOFT(cur, ids);
52 break;
55 ids[cur] = sound->id;
58 done:
59 ALCcontext_DecRef(context);
62 AL_API ALvoid AL_APIENTRY alDeleteFontsoundsSOFT(ALsizei n, const ALuint *ids)
64 ALCdevice *device;
65 ALCcontext *context;
66 ALfontsound *inst;
67 ALsizei i;
69 context = GetContextRef();
70 if(!context) return;
72 if(!(n >= 0))
73 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
75 device = context->Device;
76 for(i = 0;i < n;i++)
78 /* Check for valid ID */
79 if((inst=LookupFontsound(device, ids[i])) == NULL)
80 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
81 if(ReadRef(&inst->ref) != 0)
82 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
85 for(i = 0;i < n;i++)
87 if((inst=LookupFontsound(device, ids[i])) != NULL)
88 DeleteFontsound(device, inst);
91 done:
92 ALCcontext_DecRef(context);
95 AL_API ALboolean AL_APIENTRY alIsFontsoundSOFT(ALuint id)
97 ALCcontext *context;
98 ALboolean ret;
100 context = GetContextRef();
101 if(!context) return AL_FALSE;
103 ret = LookupFontsound(context->Device, id) ? AL_TRUE : AL_FALSE;
105 ALCcontext_DecRef(context);
107 return ret;
110 AL_API void AL_APIENTRY alFontsoundiSOFT(ALuint id, ALenum param, ALint value)
112 ALCdevice *device;
113 ALCcontext *context;
114 ALfontsound *sound;
116 context = GetContextRef();
117 if(!context) return;
119 device = context->Device;
120 if(!(sound=LookupFontsound(device, id)))
121 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
122 if(ReadRef(&sound->ref) != 0)
123 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
125 ALfontsound_setPropi(sound, context, param, value);
127 done:
128 ALCcontext_DecRef(context);
131 AL_API void AL_APIENTRY alFontsound2iSOFT(ALuint id, ALenum param, ALint value1, ALint value2)
133 ALCdevice *device;
134 ALCcontext *context;
135 ALfontsound *sound;
137 context = GetContextRef();
138 if(!context) return;
140 device = context->Device;
141 if(!(sound=LookupFontsound(device, id)))
142 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
143 if(ReadRef(&sound->ref) != 0)
144 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
145 switch(param)
147 case AL_KEY_RANGE_SOFT:
148 if(!(value1 >= 0 && value1 <= 127 && value2 >= 0 && value2 <= 127 && value2 >= value1))
149 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
150 sound->MinKey = value1;
151 sound->MaxKey = value2;
152 break;
154 case AL_VELOCITY_RANGE_SOFT:
155 if(!(value1 >= 0 && value1 <= 127 && value2 >= 0 && value2 <= 127 && value2 >= value1))
156 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
157 sound->MinVelocity = value1;
158 sound->MaxVelocity = value2;
159 break;
161 default:
162 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
165 done:
166 ALCcontext_DecRef(context);
169 AL_API void AL_APIENTRY alFontsoundivSOFT(ALuint id, ALenum param, const ALint *values)
171 ALCdevice *device;
172 ALCcontext *context;
173 ALfontsound *sound;
175 switch(param)
177 case AL_KEY_RANGE_SOFT:
178 case AL_VELOCITY_RANGE_SOFT:
179 alFontsound2iSOFT(id, param, values[0], values[1]);
180 return;
182 case AL_MOD_LFO_TO_PITCH_SOFT:
183 case AL_VIBRATO_LFO_TO_PITCH_SOFT:
184 case AL_MOD_ENV_TO_PITCH_SOFT:
185 case AL_FILTER_CUTOFF_SOFT:
186 case AL_FILTER_RESONANCE_SOFT:
187 case AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT:
188 case AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT:
189 case AL_MOD_LFO_TO_VOLUME_SOFT:
190 case AL_CHORUS_SEND_SOFT:
191 case AL_REVERB_SEND_SOFT:
192 case AL_PAN_SOFT:
193 case AL_MOD_LFO_DELAY_SOFT:
194 case AL_MOD_LFO_FREQUENCY_SOFT:
195 case AL_VIBRATO_LFO_DELAY_SOFT:
196 case AL_VIBRATO_LFO_FREQUENCY_SOFT:
197 case AL_MOD_ENV_DELAYTIME_SOFT:
198 case AL_MOD_ENV_ATTACKTIME_SOFT:
199 case AL_MOD_ENV_HOLDTIME_SOFT:
200 case AL_MOD_ENV_DECAYTIME_SOFT:
201 case AL_MOD_ENV_SUSTAINVOLUME_SOFT:
202 case AL_MOD_ENV_RELEASETIME_SOFT:
203 case AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT:
204 case AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT:
205 case AL_VOLUME_ENV_DELAYTIME_SOFT:
206 case AL_VOLUME_ENV_ATTACKTIME_SOFT:
207 case AL_VOLUME_ENV_HOLDTIME_SOFT:
208 case AL_VOLUME_ENV_DECAYTIME_SOFT:
209 case AL_VOLUME_ENV_SUSTAINVOLUME_SOFT:
210 case AL_VOLUME_ENV_RELEASETIME_SOFT:
211 case AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT:
212 case AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT:
213 case AL_ATTENUATION_SOFT:
214 case AL_TUNING_COARSE_SOFT:
215 case AL_TUNING_FINE_SOFT:
216 case AL_LOOP_MODE_SOFT:
217 case AL_TUNING_SCALE_SOFT:
218 case AL_EXCLUSIVE_CLASS_SOFT:
219 case AL_SAMPLE_START_SOFT:
220 case AL_SAMPLE_END_SOFT:
221 case AL_SAMPLE_LOOP_START_SOFT:
222 case AL_SAMPLE_LOOP_END_SOFT:
223 case AL_SAMPLE_RATE_SOFT:
224 case AL_BASE_KEY_SOFT:
225 case AL_KEY_CORRECTION_SOFT:
226 case AL_SAMPLE_TYPE_SOFT:
227 case AL_FONTSOUND_LINK_SOFT:
228 alFontsoundiSOFT(id, param, values[0]);
229 return;
232 context = GetContextRef();
233 if(!context) return;
235 device = context->Device;
236 if(!(sound=LookupFontsound(device, id)))
237 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
238 if(ReadRef(&sound->ref) != 0)
239 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
240 switch(param)
242 default:
243 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
246 done:
247 ALCcontext_DecRef(context);
250 AL_API void AL_APIENTRY alGetFontsoundivSOFT(ALuint id, ALenum param, ALint *values)
252 ALCdevice *device;
253 ALCcontext *context;
254 const ALfontsound *sound;
255 ALfontsound *link;
256 ALbuffer *buffer;
258 context = GetContextRef();
259 if(!context) return;
261 device = context->Device;
262 if(!(sound=LookupFontsound(device, id)))
263 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
264 switch(param)
266 case AL_BUFFER:
267 buffer = ATOMIC_LOAD(&sound->Buffer);
268 values[0] = (buffer ? buffer->id : 0);
269 break;
271 case AL_MOD_LFO_TO_PITCH_SOFT:
272 values[0] = sound->ModLfoToPitch;
273 break;
275 case AL_VIBRATO_LFO_TO_PITCH_SOFT:
276 values[0] = sound->VibratoLfoToPitch;
277 break;
279 case AL_MOD_ENV_TO_PITCH_SOFT:
280 values[0] = sound->ModEnvToPitch;
281 break;
283 case AL_FILTER_CUTOFF_SOFT:
284 values[0] = sound->FilterCutoff;
285 break;
287 case AL_FILTER_RESONANCE_SOFT:
288 values[0] = sound->FilterQ;
289 break;
291 case AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT:
292 values[0] = sound->ModLfoToFilterCutoff;
293 break;
295 case AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT:
296 values[0] = sound->ModEnvToFilterCutoff;
297 break;
299 case AL_MOD_LFO_TO_VOLUME_SOFT:
300 values[0] = sound->ModLfoToVolume;
301 break;
303 case AL_CHORUS_SEND_SOFT:
304 values[0] = sound->ChorusSend;
305 break;
307 case AL_REVERB_SEND_SOFT:
308 values[0] = sound->ReverbSend;
309 break;
311 case AL_PAN_SOFT:
312 values[0] = sound->Pan;
313 break;
315 case AL_MOD_LFO_DELAY_SOFT:
316 values[0] = sound->ModLfo.Delay;
317 break;
318 case AL_MOD_LFO_FREQUENCY_SOFT:
319 values[0] = sound->ModLfo.Frequency;
320 break;
322 case AL_VIBRATO_LFO_DELAY_SOFT:
323 values[0] = sound->VibratoLfo.Delay;
324 break;
325 case AL_VIBRATO_LFO_FREQUENCY_SOFT:
326 values[0] = sound->VibratoLfo.Frequency;
327 break;
329 case AL_MOD_ENV_DELAYTIME_SOFT:
330 values[0] = sound->ModEnv.DelayTime;
331 break;
332 case AL_MOD_ENV_ATTACKTIME_SOFT:
333 values[0] = sound->ModEnv.AttackTime;
334 break;
335 case AL_MOD_ENV_HOLDTIME_SOFT:
336 values[0] = sound->ModEnv.HoldTime;
337 break;
338 case AL_MOD_ENV_DECAYTIME_SOFT:
339 values[0] = sound->ModEnv.DecayTime;
340 break;
341 case AL_MOD_ENV_SUSTAINVOLUME_SOFT:
342 values[0] = sound->ModEnv.SustainAttn;
343 break;
344 case AL_MOD_ENV_RELEASETIME_SOFT:
345 values[0] = sound->ModEnv.ReleaseTime;
346 break;
347 case AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT:
348 values[0] = sound->ModEnv.KeyToHoldTime;
349 break;
350 case AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT:
351 values[0] = sound->ModEnv.KeyToDecayTime;
352 break;
354 case AL_VOLUME_ENV_DELAYTIME_SOFT:
355 values[0] = sound->VolEnv.DelayTime;
356 break;
357 case AL_VOLUME_ENV_ATTACKTIME_SOFT:
358 values[0] = sound->VolEnv.AttackTime;
359 break;
360 case AL_VOLUME_ENV_HOLDTIME_SOFT:
361 values[0] = sound->VolEnv.HoldTime;
362 break;
363 case AL_VOLUME_ENV_DECAYTIME_SOFT:
364 values[0] = sound->VolEnv.DecayTime;
365 break;
366 case AL_VOLUME_ENV_SUSTAINVOLUME_SOFT:
367 values[0] = sound->VolEnv.SustainAttn;
368 break;
369 case AL_VOLUME_ENV_RELEASETIME_SOFT:
370 values[0] = sound->VolEnv.ReleaseTime;
371 break;
372 case AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT:
373 values[0] = sound->VolEnv.KeyToHoldTime;
374 break;
375 case AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT:
376 values[0] = sound->VolEnv.KeyToDecayTime;
377 break;
379 case AL_KEY_RANGE_SOFT:
380 values[0] = sound->MinKey;
381 values[1] = sound->MaxKey;
382 break;
384 case AL_VELOCITY_RANGE_SOFT:
385 values[0] = sound->MinVelocity;
386 values[1] = sound->MaxVelocity;
387 break;
389 case AL_ATTENUATION_SOFT:
390 values[0] = sound->Attenuation;
391 break;
393 case AL_TUNING_COARSE_SOFT:
394 values[0] = sound->CoarseTuning;
395 break;
396 case AL_TUNING_FINE_SOFT:
397 values[0] = sound->FineTuning;
398 break;
400 case AL_LOOP_MODE_SOFT:
401 values[0] = sound->LoopMode;
402 break;
404 case AL_TUNING_SCALE_SOFT:
405 values[0] = sound->TuningScale;
406 break;
408 case AL_EXCLUSIVE_CLASS_SOFT:
409 values[0] = sound->ExclusiveClass;
410 break;
412 case AL_SAMPLE_START_SOFT:
413 values[0] = sound->Start;
414 break;
416 case AL_SAMPLE_END_SOFT:
417 values[0] = sound->End;
418 break;
420 case AL_SAMPLE_LOOP_START_SOFT:
421 values[0] = sound->LoopStart;
422 break;
424 case AL_SAMPLE_LOOP_END_SOFT:
425 values[0] = sound->LoopEnd;
426 break;
428 case AL_SAMPLE_RATE_SOFT:
429 values[0] = sound->SampleRate;
430 break;
432 case AL_BASE_KEY_SOFT:
433 values[0] = sound->PitchKey;
434 break;
436 case AL_KEY_CORRECTION_SOFT:
437 values[0] = sound->PitchCorrection;
438 break;
440 case AL_SAMPLE_TYPE_SOFT:
441 values[0] = sound->SampleType;
442 break;
444 case AL_FONTSOUND_LINK_SOFT:
445 link = ATOMIC_LOAD(&sound->Link);
446 values[0] = (link ? link->id : 0);
447 break;
449 default:
450 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
453 done:
454 ALCcontext_DecRef(context);
457 AL_API void AL_APIENTRY alFontsoundModulatoriSOFT(ALuint id, ALsizei stage, ALenum param, ALint value)
459 ALCdevice *device;
460 ALCcontext *context;
461 ALfontsound *sound;
463 context = GetContextRef();
464 if(!context) return;
466 device = context->Device;
467 if(!(sound=LookupFontsound(device, id)))
468 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
469 ALfontsound_setModStagei(sound, context, stage, param, value);
471 done:
472 ALCcontext_DecRef(context);
475 AL_API void AL_APIENTRY alGetFontsoundModulatorivSOFT(ALuint id, ALsizei stage, ALenum param, ALint *values)
477 ALCdevice *device;
478 ALCcontext *context;
479 ALfontsound *sound;
481 context = GetContextRef();
482 if(!context) return;
484 device = context->Device;
485 if(!(sound=LookupFontsound(device, id)))
486 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
487 ALfontsound_getModStagei(sound, context, stage, param, values);
489 done:
490 ALCcontext_DecRef(context);
494 ALfontsound *NewFontsound(ALCcontext *context)
496 ALCdevice *device = context->Device;
497 ALfontsound *sound;
498 ALenum err;
500 sound = calloc(1, sizeof(*sound));
501 if(!sound)
502 SET_ERROR_AND_RETURN_VALUE(context, AL_OUT_OF_MEMORY, NULL);
503 ALfontsound_Construct(sound);
505 err = NewThunkEntry(&sound->id);
506 if(err == AL_NO_ERROR)
507 err = InsertUIntMapEntry(&device->FontsoundMap, sound->id, sound);
508 if(err != AL_NO_ERROR)
510 ALfontsound_Destruct(sound);
511 memset(sound, 0, sizeof(*sound));
512 free(sound);
514 SET_ERROR_AND_RETURN_VALUE(context, err, NULL);
517 return sound;
520 void DeleteFontsound(ALCdevice *device, ALfontsound *sound)
522 RemoveFontsound(device, sound->id);
524 ALfontsound_Destruct(sound);
526 memset(sound, 0, sizeof(*sound));
527 free(sound);
531 static void ALfontsound_Construct(ALfontsound *self)
533 InitRef(&self->ref, 0);
535 ATOMIC_INIT(&self->Buffer, NULL);
537 self->MinKey = 0;
538 self->MaxKey = 127;
539 self->MinVelocity = 0;
540 self->MaxVelocity = 127;
542 self->ModLfoToPitch = 0;
543 self->VibratoLfoToPitch = 0;
544 self->ModEnvToPitch = 0;
546 self->FilterCutoff = 13500;
547 self->FilterQ = 0;
548 self->ModLfoToFilterCutoff = 0;
549 self->ModEnvToFilterCutoff = 0;
550 self->ModLfoToVolume = 0;
552 self->ChorusSend = 0;
553 self->ReverbSend = 0;
555 self->Pan = 0;
557 self->ModLfo.Delay = 0;
558 self->ModLfo.Frequency = 0;
560 self->VibratoLfo.Delay = 0;
561 self->VibratoLfo.Frequency = 0;
563 self->ModEnv.DelayTime = -12000;
564 self->ModEnv.AttackTime = -12000;
565 self->ModEnv.HoldTime = -12000;
566 self->ModEnv.DecayTime = -12000;
567 self->ModEnv.SustainAttn = 0;
568 self->ModEnv.ReleaseTime = -12000;
569 self->ModEnv.KeyToHoldTime = 0;
570 self->ModEnv.KeyToDecayTime = 0;
572 self->VolEnv.DelayTime = -12000;
573 self->VolEnv.AttackTime = -12000;
574 self->VolEnv.HoldTime = -12000;
575 self->VolEnv.DecayTime = -12000;
576 self->VolEnv.SustainAttn = 0;
577 self->VolEnv.ReleaseTime = -12000;
578 self->VolEnv.KeyToHoldTime = 0;
579 self->VolEnv.KeyToDecayTime = 0;
581 self->Attenuation = 0;
583 self->CoarseTuning = 0;
584 self->FineTuning = 0;
586 self->LoopMode = AL_NONE;
588 self->TuningScale = 100;
590 self->ExclusiveClass = 0;
592 self->Start = 0;
593 self->End = 0;
594 self->LoopStart = 0;
595 self->LoopEnd = 0;
596 self->SampleRate = 0;
597 self->PitchKey = 0;
598 self->PitchCorrection = 0;
599 self->SampleType = AL_MONO_SOFT;
601 ATOMIC_INIT(&self->Link, NULL);
603 InitUIntMap(&self->ModulatorMap, ~0);
605 self->id = 0;
608 static void ALfontsound_Destruct(ALfontsound *self)
610 ALfontsound *link;
611 ALbuffer *buffer;
612 ALsizei i;
614 FreeThunkEntry(self->id);
615 self->id = 0;
617 if((buffer=ATOMIC_EXCHANGE(ALbuffer*, &self->Buffer, NULL)) != NULL)
618 DecrementRef(&buffer->ref);
620 if((link=ATOMIC_EXCHANGE(ALfontsound*, &self->Link, NULL)) != NULL)
621 DecrementRef(&link->ref);
623 for(i = 0;i < self->ModulatorMap.size;i++)
625 free(self->ModulatorMap.array[i].value);
626 self->ModulatorMap.array[i].value = NULL;
628 ResetUIntMap(&self->ModulatorMap);
631 void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, ALint value)
633 ALfontsound *link;
634 ALbuffer *buffer;
636 switch(param)
638 case AL_BUFFER:
639 buffer = value ? LookupBuffer(context->Device, value) : NULL;
640 if(value && !buffer)
641 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
642 else if(buffer)
644 /* Buffer must have a non-0 length, and must be mono. */
645 if(buffer->SampleLen <= 0 || buffer->FmtChannels != FmtMono)
646 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
649 if(buffer) IncrementRef(&buffer->ref);
650 if((buffer=ATOMIC_EXCHANGE(ALbuffer*, &self->Buffer, buffer)) != NULL)
651 DecrementRef(&buffer->ref);
652 break;
654 case AL_MOD_LFO_TO_PITCH_SOFT:
655 self->ModLfoToPitch = value;
656 break;
658 case AL_VIBRATO_LFO_TO_PITCH_SOFT:
659 self->VibratoLfoToPitch = value;
660 break;
662 case AL_MOD_ENV_TO_PITCH_SOFT:
663 self->ModEnvToPitch = value;
664 break;
666 case AL_FILTER_CUTOFF_SOFT:
667 self->FilterCutoff = value;
668 break;
670 case AL_FILTER_RESONANCE_SOFT:
671 if(!(value >= 0))
672 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
673 self->FilterQ = value;
674 break;
676 case AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT:
677 self->ModLfoToFilterCutoff = value;
678 break;
680 case AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT:
681 self->ModEnvToFilterCutoff = value;
682 break;
684 case AL_MOD_LFO_TO_VOLUME_SOFT:
685 self->ModLfoToVolume = value;
686 break;
688 case AL_CHORUS_SEND_SOFT:
689 if(!(value >= 0 && value <= 1000))
690 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
691 self->ChorusSend = value;
692 break;
693 case AL_REVERB_SEND_SOFT:
694 if(!(value >= 0 && value <= 1000))
695 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
696 self->ReverbSend = value;
697 break;
699 case AL_PAN_SOFT:
700 self->Pan = value;
701 break;
703 case AL_MOD_LFO_DELAY_SOFT:
704 self->ModLfo.Delay = value;
705 break;
706 case AL_MOD_LFO_FREQUENCY_SOFT:
707 self->ModLfo.Frequency = value;
708 break;
710 case AL_VIBRATO_LFO_DELAY_SOFT:
711 self->VibratoLfo.Delay = value;
712 break;
713 case AL_VIBRATO_LFO_FREQUENCY_SOFT:
714 self->VibratoLfo.Frequency = value;
715 break;
717 case AL_MOD_ENV_DELAYTIME_SOFT:
718 self->ModEnv.DelayTime = value;
719 break;
720 case AL_MOD_ENV_ATTACKTIME_SOFT:
721 self->ModEnv.AttackTime = value;
722 break;
723 case AL_MOD_ENV_HOLDTIME_SOFT:
724 self->ModEnv.HoldTime = value;
725 break;
726 case AL_MOD_ENV_DECAYTIME_SOFT:
727 self->ModEnv.DecayTime = value;
728 break;
729 case AL_MOD_ENV_SUSTAINVOLUME_SOFT:
730 self->ModEnv.SustainAttn = value;
731 break;
732 case AL_MOD_ENV_RELEASETIME_SOFT:
733 self->ModEnv.ReleaseTime = value;
734 break;
735 case AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT:
736 self->ModEnv.KeyToHoldTime = value;
737 break;
738 case AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT:
739 self->ModEnv.KeyToDecayTime = value;
740 break;
742 case AL_VOLUME_ENV_DELAYTIME_SOFT:
743 self->VolEnv.DelayTime = value;
744 break;
745 case AL_VOLUME_ENV_ATTACKTIME_SOFT:
746 self->VolEnv.AttackTime = value;
747 break;
748 case AL_VOLUME_ENV_HOLDTIME_SOFT:
749 self->VolEnv.HoldTime = value;
750 break;
751 case AL_VOLUME_ENV_DECAYTIME_SOFT:
752 self->VolEnv.DecayTime = value;
753 break;
754 case AL_VOLUME_ENV_SUSTAINVOLUME_SOFT:
755 self->VolEnv.SustainAttn = value;
756 break;
757 case AL_VOLUME_ENV_RELEASETIME_SOFT:
758 self->VolEnv.ReleaseTime = value;
759 break;
760 case AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT:
761 self->VolEnv.KeyToHoldTime = value;
762 break;
763 case AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT:
764 self->VolEnv.KeyToDecayTime = value;
765 break;
767 case AL_ATTENUATION_SOFT:
768 if(!(value >= 0))
769 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
770 self->Attenuation = value;
771 break;
773 case AL_TUNING_COARSE_SOFT:
774 self->CoarseTuning = value;
775 break;
776 case AL_TUNING_FINE_SOFT:
777 self->FineTuning = value;
778 break;
780 case AL_LOOP_MODE_SOFT:
781 if(!(value == AL_NONE || value == AL_LOOP_CONTINUOUS_SOFT ||
782 value == AL_LOOP_UNTIL_RELEASE_SOFT))
783 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
784 self->LoopMode = value;
785 break;
787 case AL_TUNING_SCALE_SOFT:
788 self->TuningScale = value;
789 break;
791 case AL_EXCLUSIVE_CLASS_SOFT:
792 self->ExclusiveClass = value;
793 break;
795 case AL_SAMPLE_START_SOFT:
796 self->Start = value;
797 break;
799 case AL_SAMPLE_END_SOFT:
800 self->End = value;
801 break;
803 case AL_SAMPLE_LOOP_START_SOFT:
804 self->LoopStart = value;
805 break;
807 case AL_SAMPLE_LOOP_END_SOFT:
808 self->LoopEnd = value;
809 break;
811 case AL_SAMPLE_RATE_SOFT:
812 if(!(value > 0))
813 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
814 self->SampleRate = value;
815 break;
817 case AL_BASE_KEY_SOFT:
818 if(!((value >= 0 && value <= 127) || value == 255))
819 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
820 self->PitchKey = value;
821 break;
823 case AL_KEY_CORRECTION_SOFT:
824 if(!(value >= -99 && value <= 99))
825 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
826 self->PitchCorrection = value;
827 break;
829 case AL_SAMPLE_TYPE_SOFT:
830 if(!(value == AL_MONO_SOFT || value == AL_RIGHT_SOFT || value == AL_LEFT_SOFT))
831 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
832 self->SampleType = value;
833 break;
835 case AL_FONTSOUND_LINK_SOFT:
836 link = value ? LookupFontsound(context->Device, value) : NULL;
837 if(value && !link)
838 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
840 if(link) IncrementRef(&link->ref);
841 if((link=ATOMIC_EXCHANGE(ALfontsound*, &self->Link, link)) != NULL)
842 DecrementRef(&link->ref);
843 break;
845 default:
846 SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
850 static ALsfmodulator *ALfontsound_getModStage(ALfontsound *self, ALsizei stage)
852 ALsfmodulator *ret = LookupModulator(self, stage);
853 if(!ret)
855 static const ALsfmodulator moddef = {
856 { { AL_ONE_SOFT, AL_UNORM_SOFT, AL_LINEAR_SOFT },
857 { AL_ONE_SOFT, AL_UNORM_SOFT, AL_LINEAR_SOFT } },
859 AL_LINEAR_SOFT,
860 AL_NONE
862 ret = malloc(sizeof(ALsfmodulator[4]));
863 ret[0] = moddef;
864 ret[1] = moddef;
865 ret[2] = moddef;
866 ret[3] = moddef;
867 InsertUIntMapEntry(&self->ModulatorMap, stage>>2, ret);
868 ret += stage&3;
870 return ret;
873 void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint value)
875 ALint srcidx = 0;
877 if(ReadRef(&self->ref) != 0)
878 SET_ERROR_AND_RETURN(context, AL_INVALID_OPERATION);
879 switch(param)
881 case AL_SOURCE1_INPUT_SOFT:
882 srcidx++;
883 /* fall-through */
884 case AL_SOURCE0_INPUT_SOFT:
885 if(!(value == AL_ONE_SOFT || value == AL_NOTEON_VELOCITY_SOFT ||
886 value == AL_NOTEON_KEY_SOFT || value == AL_KEYPRESSURE_SOFT ||
887 value == AL_CHANNELPRESSURE_SOFT || value == AL_PITCHBEND_SOFT ||
888 value == AL_PITCHBEND_SENSITIVITY_SOFT ||
889 IsValidCtrlInput(value)))
890 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
891 ALfontsound_getModStage(self, stage)->Source[srcidx].Input = value;
892 break;
894 case AL_SOURCE1_TYPE_SOFT:
895 srcidx++;
896 /* fall-through */
897 case AL_SOURCE0_TYPE_SOFT:
898 if(!(value == AL_UNORM_SOFT || value == AL_UNORM_REV_SOFT ||
899 value == AL_SNORM_SOFT || value == AL_SNORM_REV_SOFT))
900 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
901 ALfontsound_getModStage(self, stage)->Source[srcidx].Type = value;
902 break;
904 case AL_SOURCE1_FORM_SOFT:
905 srcidx++;
906 /* fall-through */
907 case AL_SOURCE0_FORM_SOFT:
908 if(!(value == AL_LINEAR_SOFT || value == AL_CONCAVE_SOFT ||
909 value == AL_CONVEX_SOFT || value == AL_SWITCH_SOFT))
910 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
911 ALfontsound_getModStage(self, stage)->Source[srcidx].Form = value;
912 break;
914 case AL_AMOUNT_SOFT:
915 ALfontsound_getModStage(self, stage)->Amount = value;
916 break;
918 case AL_TRANSFORM_OP_SOFT:
919 if(!(value == AL_LINEAR_SOFT || value == AL_ABSOLUTE_SOFT))
920 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
921 ALfontsound_getModStage(self, stage)->TransformOp = value;
922 break;
924 case AL_DESTINATION_SOFT:
925 if(!(value == AL_MOD_LFO_TO_PITCH_SOFT || value == AL_VIBRATO_LFO_TO_PITCH_SOFT ||
926 value == AL_MOD_ENV_TO_PITCH_SOFT || value == AL_FILTER_CUTOFF_SOFT ||
927 value == AL_FILTER_RESONANCE_SOFT || value == AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT ||
928 value == AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT || value == AL_MOD_LFO_TO_VOLUME_SOFT ||
929 value == AL_CHORUS_SEND_SOFT || value == AL_REVERB_SEND_SOFT || value == AL_PAN_SOFT ||
930 value == AL_MOD_LFO_DELAY_SOFT || value == AL_MOD_LFO_FREQUENCY_SOFT ||
931 value == AL_VIBRATO_LFO_DELAY_SOFT || value == AL_VIBRATO_LFO_FREQUENCY_SOFT ||
932 value == AL_MOD_ENV_DELAYTIME_SOFT || value == AL_MOD_ENV_ATTACKTIME_SOFT ||
933 value == AL_MOD_ENV_HOLDTIME_SOFT || value == AL_MOD_ENV_DECAYTIME_SOFT ||
934 value == AL_MOD_ENV_SUSTAINVOLUME_SOFT || value == AL_MOD_ENV_RELEASETIME_SOFT ||
935 value == AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT || value == AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT ||
936 value == AL_VOLUME_ENV_DELAYTIME_SOFT || value == AL_VOLUME_ENV_ATTACKTIME_SOFT ||
937 value == AL_VOLUME_ENV_HOLDTIME_SOFT || value == AL_VOLUME_ENV_DECAYTIME_SOFT ||
938 value == AL_VOLUME_ENV_SUSTAINVOLUME_SOFT || value == AL_VOLUME_ENV_RELEASETIME_SOFT ||
939 value == AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT || value == AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT ||
940 value == AL_ATTENUATION_SOFT || value == AL_TUNING_COARSE_SOFT ||
941 value == AL_TUNING_FINE_SOFT || value == AL_TUNING_SCALE_SOFT))
942 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
943 ALfontsound_getModStage(self, stage)->Dest = value;
944 break;
946 default:
947 SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
951 static void ALfontsound_getModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint *values)
953 ALsfmodulator *mod = LookupModulator(self, stage);
954 ALint srcidx = 0;
956 switch(param)
958 case AL_SOURCE1_INPUT_SOFT:
959 srcidx++;
960 /* fall-through */
961 case AL_SOURCE0_INPUT_SOFT:
962 values[0] = mod ? mod->Source[srcidx].Input : AL_ONE_SOFT;
963 break;
965 case AL_SOURCE1_TYPE_SOFT:
966 srcidx++;
967 /* fall-through */
968 case AL_SOURCE0_TYPE_SOFT:
969 values[0] = mod ? mod->Source[srcidx].Type : AL_UNORM_SOFT;
970 break;
972 case AL_SOURCE1_FORM_SOFT:
973 srcidx++;
974 /* fall-through */
975 case AL_SOURCE0_FORM_SOFT:
976 values[0] = mod ? mod->Source[srcidx].Form : AL_LINEAR_SOFT;
977 break;
979 case AL_AMOUNT_SOFT:
980 values[0] = mod ? mod->Amount : 0;
981 break;
983 case AL_TRANSFORM_OP_SOFT:
984 values[0] = mod ? mod->TransformOp : AL_LINEAR_SOFT;
985 break;
987 case AL_DESTINATION_SOFT:
988 values[0] = mod ? mod->Dest : AL_NONE;
989 break;
991 default:
992 SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
997 /* ReleaseALFontsounds
999 * Called to destroy any fontsounds that still exist on the device
1001 void ReleaseALFontsounds(ALCdevice *device)
1003 ALsizei i;
1004 for(i = 0;i < device->FontsoundMap.size;i++)
1006 ALfontsound *temp = device->FontsoundMap.array[i].value;
1007 device->FontsoundMap.array[i].value = NULL;
1009 ALfontsound_Destruct(temp);
1011 memset(temp, 0, sizeof(*temp));
1012 free(temp);