Simplify setting a fontsound link
[openal-soft.git] / OpenAL32 / alFontsound.c
blob1e2c303d35ae7ca04b2864af29daad4ccdc4cb0e
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);
18 extern inline struct ALsfmodulator *LookupModulator(ALfontsound *sound, ALuint id);
19 extern inline struct ALsfmodulator *RemoveModulator(ALfontsound *sound, ALuint id);
21 static void ALfontsound_Construct(ALfontsound *self);
22 static void ALfontsound_Destruct(ALfontsound *self);
23 void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, ALint value);
24 static ALsfmodulator *ALfontsound_getModStage(ALfontsound *self, ALsizei stage);
25 void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint value);
26 static void ALfontsound_getModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint *values);
29 AL_API void AL_APIENTRY alGenFontsoundsSOFT(ALsizei n, ALuint *ids)
31 ALCcontext *context;
32 ALsizei cur = 0;
34 context = GetContextRef();
35 if(!context) return;
37 if(!(n >= 0))
38 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
40 for(cur = 0;cur < n;cur++)
42 ALfontsound *sound = NewFontsound(context);
43 if(!sound)
45 alDeleteFontsoundsSOFT(cur, ids);
46 break;
49 ids[cur] = sound->id;
52 done:
53 ALCcontext_DecRef(context);
56 AL_API ALvoid AL_APIENTRY alDeleteFontsoundsSOFT(ALsizei n, const ALuint *ids)
58 ALCdevice *device;
59 ALCcontext *context;
60 ALfontsound *inst;
61 ALsizei i;
63 context = GetContextRef();
64 if(!context) return;
66 if(!(n >= 0))
67 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
69 device = context->Device;
70 for(i = 0;i < n;i++)
72 /* Check for valid ID */
73 if((inst=LookupFontsound(device, ids[i])) == NULL)
74 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
75 if(ReadRef(&inst->ref) != 0)
76 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
79 for(i = 0;i < n;i++)
81 if((inst=LookupFontsound(device, ids[i])) != NULL)
82 DeleteFontsound(device, inst);
85 done:
86 ALCcontext_DecRef(context);
89 AL_API ALboolean AL_APIENTRY alIsFontsoundSOFT(ALuint id)
91 ALCcontext *context;
92 ALboolean ret;
94 context = GetContextRef();
95 if(!context) return AL_FALSE;
97 ret = LookupFontsound(context->Device, id) ? AL_TRUE : AL_FALSE;
99 ALCcontext_DecRef(context);
101 return ret;
104 AL_API void AL_APIENTRY alFontsoundiSOFT(ALuint id, ALenum param, ALint value)
106 ALCdevice *device;
107 ALCcontext *context;
108 ALfontsound *sound;
110 context = GetContextRef();
111 if(!context) return;
113 device = context->Device;
114 if(!(sound=LookupFontsound(device, id)))
115 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
116 if(ReadRef(&sound->ref) != 0)
117 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
119 ALfontsound_setPropi(sound, context, param, value);
121 done:
122 ALCcontext_DecRef(context);
125 AL_API void AL_APIENTRY alFontsound2iSOFT(ALuint id, ALenum param, ALint value1, ALint value2)
127 ALCdevice *device;
128 ALCcontext *context;
129 ALfontsound *sound;
131 context = GetContextRef();
132 if(!context) return;
134 device = context->Device;
135 if(!(sound=LookupFontsound(device, id)))
136 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
137 if(ReadRef(&sound->ref) != 0)
138 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
139 switch(param)
141 case AL_KEY_RANGE_SOFT:
142 if(!(value1 >= 0 && value1 <= 127 && value2 >= 0 && value2 <= 127 && value2 >= value1))
143 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
144 sound->MinKey = value1;
145 sound->MaxKey = value2;
146 break;
148 case AL_VELOCITY_RANGE_SOFT:
149 if(!(value1 >= 0 && value1 <= 127 && value2 >= 0 && value2 <= 127 && value2 >= value1))
150 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
151 sound->MinVelocity = value1;
152 sound->MaxVelocity = value2;
153 break;
155 default:
156 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
159 done:
160 ALCcontext_DecRef(context);
163 AL_API void AL_APIENTRY alFontsoundivSOFT(ALuint id, ALenum param, const ALint *values)
165 ALCdevice *device;
166 ALCcontext *context;
167 ALfontsound *sound;
169 switch(param)
171 case AL_KEY_RANGE_SOFT:
172 case AL_VELOCITY_RANGE_SOFT:
173 alFontsound2iSOFT(id, param, values[0], values[1]);
174 return;
176 case AL_MOD_LFO_TO_PITCH_SOFT:
177 case AL_VIBRATO_LFO_TO_PITCH_SOFT:
178 case AL_MOD_ENV_TO_PITCH_SOFT:
179 case AL_FILTER_CUTOFF_SOFT:
180 case AL_FILTER_RESONANCE_SOFT:
181 case AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT:
182 case AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT:
183 case AL_MOD_LFO_TO_VOLUME_SOFT:
184 case AL_CHORUS_SEND_SOFT:
185 case AL_REVERB_SEND_SOFT:
186 case AL_PAN_SOFT:
187 case AL_MOD_LFO_DELAY_SOFT:
188 case AL_MOD_LFO_FREQUENCY_SOFT:
189 case AL_VIBRATO_LFO_DELAY_SOFT:
190 case AL_VIBRATO_LFO_FREQUENCY_SOFT:
191 case AL_MOD_ENV_DELAYTIME_SOFT:
192 case AL_MOD_ENV_ATTACKTIME_SOFT:
193 case AL_MOD_ENV_HOLDTIME_SOFT:
194 case AL_MOD_ENV_DECAYTIME_SOFT:
195 case AL_MOD_ENV_SUSTAINVOLUME_SOFT:
196 case AL_MOD_ENV_RELEASETIME_SOFT:
197 case AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT:
198 case AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT:
199 case AL_VOLUME_ENV_DELAYTIME_SOFT:
200 case AL_VOLUME_ENV_ATTACKTIME_SOFT:
201 case AL_VOLUME_ENV_HOLDTIME_SOFT:
202 case AL_VOLUME_ENV_DECAYTIME_SOFT:
203 case AL_VOLUME_ENV_SUSTAINVOLUME_SOFT:
204 case AL_VOLUME_ENV_RELEASETIME_SOFT:
205 case AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT:
206 case AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT:
207 case AL_ATTENUATION_SOFT:
208 case AL_TUNING_COARSE_SOFT:
209 case AL_TUNING_FINE_SOFT:
210 case AL_LOOP_MODE_SOFT:
211 case AL_TUNING_SCALE_SOFT:
212 case AL_EXCLUSIVE_CLASS_SOFT:
213 case AL_SAMPLE_START_SOFT:
214 case AL_SAMPLE_END_SOFT:
215 case AL_SAMPLE_LOOP_START_SOFT:
216 case AL_SAMPLE_LOOP_END_SOFT:
217 case AL_SAMPLE_RATE_SOFT:
218 case AL_BASE_KEY_SOFT:
219 case AL_KEY_CORRECTION_SOFT:
220 case AL_SAMPLE_TYPE_SOFT:
221 case AL_FONTSOUND_LINK_SOFT:
222 alFontsoundiSOFT(id, param, values[0]);
223 return;
226 context = GetContextRef();
227 if(!context) return;
229 device = context->Device;
230 if(!(sound=LookupFontsound(device, id)))
231 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
232 if(ReadRef(&sound->ref) != 0)
233 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
234 switch(param)
236 default:
237 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
240 done:
241 ALCcontext_DecRef(context);
244 AL_API void AL_APIENTRY alGetFontsoundivSOFT(ALuint id, ALenum param, ALint *values)
246 ALCdevice *device;
247 ALCcontext *context;
248 const ALfontsound *sound;
250 context = GetContextRef();
251 if(!context) return;
253 device = context->Device;
254 if(!(sound=LookupFontsound(device, id)))
255 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
256 switch(param)
258 case AL_BUFFER:
259 values[0] = (sound->Buffer ? sound->Buffer->id : 0);
260 break;
262 case AL_MOD_LFO_TO_PITCH_SOFT:
263 values[0] = sound->ModLfoToPitch;
264 break;
266 case AL_VIBRATO_LFO_TO_PITCH_SOFT:
267 values[0] = sound->VibratoLfoToPitch;
268 break;
270 case AL_MOD_ENV_TO_PITCH_SOFT:
271 values[0] = sound->ModEnvToPitch;
272 break;
274 case AL_FILTER_CUTOFF_SOFT:
275 values[0] = sound->FilterCutoff;
276 break;
278 case AL_FILTER_RESONANCE_SOFT:
279 values[0] = sound->FilterQ;
280 break;
282 case AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT:
283 values[0] = sound->ModLfoToFilterCutoff;
284 break;
286 case AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT:
287 values[0] = sound->ModEnvToFilterCutoff;
288 break;
290 case AL_MOD_LFO_TO_VOLUME_SOFT:
291 values[0] = sound->ModLfoToVolume;
292 break;
294 case AL_CHORUS_SEND_SOFT:
295 values[0] = sound->ChorusSend;
296 break;
298 case AL_REVERB_SEND_SOFT:
299 values[0] = sound->ReverbSend;
300 break;
302 case AL_PAN_SOFT:
303 values[0] = sound->Pan;
304 break;
306 case AL_MOD_LFO_DELAY_SOFT:
307 values[0] = sound->ModLfo.Delay;
308 break;
309 case AL_MOD_LFO_FREQUENCY_SOFT:
310 values[0] = sound->ModLfo.Frequency;
311 break;
313 case AL_VIBRATO_LFO_DELAY_SOFT:
314 values[0] = sound->VibratoLfo.Delay;
315 break;
316 case AL_VIBRATO_LFO_FREQUENCY_SOFT:
317 values[0] = sound->VibratoLfo.Frequency;
318 break;
320 case AL_MOD_ENV_DELAYTIME_SOFT:
321 values[0] = sound->ModEnv.DelayTime;
322 break;
323 case AL_MOD_ENV_ATTACKTIME_SOFT:
324 values[0] = sound->ModEnv.AttackTime;
325 break;
326 case AL_MOD_ENV_HOLDTIME_SOFT:
327 values[0] = sound->ModEnv.HoldTime;
328 break;
329 case AL_MOD_ENV_DECAYTIME_SOFT:
330 values[0] = sound->ModEnv.DecayTime;
331 break;
332 case AL_MOD_ENV_SUSTAINVOLUME_SOFT:
333 values[0] = sound->ModEnv.SustainAttn;
334 break;
335 case AL_MOD_ENV_RELEASETIME_SOFT:
336 values[0] = sound->ModEnv.ReleaseTime;
337 break;
338 case AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT:
339 values[0] = sound->ModEnv.KeyToHoldTime;
340 break;
341 case AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT:
342 values[0] = sound->ModEnv.KeyToDecayTime;
343 break;
345 case AL_VOLUME_ENV_DELAYTIME_SOFT:
346 values[0] = sound->VolEnv.DelayTime;
347 break;
348 case AL_VOLUME_ENV_ATTACKTIME_SOFT:
349 values[0] = sound->VolEnv.AttackTime;
350 break;
351 case AL_VOLUME_ENV_HOLDTIME_SOFT:
352 values[0] = sound->VolEnv.HoldTime;
353 break;
354 case AL_VOLUME_ENV_DECAYTIME_SOFT:
355 values[0] = sound->VolEnv.DecayTime;
356 break;
357 case AL_VOLUME_ENV_SUSTAINVOLUME_SOFT:
358 values[0] = sound->VolEnv.SustainAttn;
359 break;
360 case AL_VOLUME_ENV_RELEASETIME_SOFT:
361 values[0] = sound->VolEnv.ReleaseTime;
362 break;
363 case AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT:
364 values[0] = sound->VolEnv.KeyToHoldTime;
365 break;
366 case AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT:
367 values[0] = sound->VolEnv.KeyToDecayTime;
368 break;
370 case AL_KEY_RANGE_SOFT:
371 values[0] = sound->MinKey;
372 values[1] = sound->MaxKey;
373 break;
375 case AL_VELOCITY_RANGE_SOFT:
376 values[0] = sound->MinVelocity;
377 values[1] = sound->MaxVelocity;
378 break;
380 case AL_ATTENUATION_SOFT:
381 values[0] = sound->Attenuation;
382 break;
384 case AL_TUNING_COARSE_SOFT:
385 values[0] = sound->CoarseTuning;
386 break;
387 case AL_TUNING_FINE_SOFT:
388 values[0] = sound->FineTuning;
389 break;
391 case AL_LOOP_MODE_SOFT:
392 values[0] = sound->LoopMode;
393 break;
395 case AL_TUNING_SCALE_SOFT:
396 values[0] = sound->TuningScale;
397 break;
399 case AL_EXCLUSIVE_CLASS_SOFT:
400 values[0] = sound->ExclusiveClass;
401 break;
403 case AL_SAMPLE_START_SOFT:
404 values[0] = sound->Start;
405 break;
407 case AL_SAMPLE_END_SOFT:
408 values[0] = sound->End;
409 break;
411 case AL_SAMPLE_LOOP_START_SOFT:
412 values[0] = sound->LoopStart;
413 break;
415 case AL_SAMPLE_LOOP_END_SOFT:
416 values[0] = sound->LoopEnd;
417 break;
419 case AL_SAMPLE_RATE_SOFT:
420 values[0] = sound->SampleRate;
421 break;
423 case AL_BASE_KEY_SOFT:
424 values[0] = sound->PitchKey;
425 break;
427 case AL_KEY_CORRECTION_SOFT:
428 values[0] = sound->PitchCorrection;
429 break;
431 case AL_SAMPLE_TYPE_SOFT:
432 values[0] = sound->SampleType;
433 break;
435 case AL_FONTSOUND_LINK_SOFT:
436 values[0] = (sound->Link ? sound->Link->id : 0);
437 break;
439 default:
440 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
443 done:
444 ALCcontext_DecRef(context);
447 AL_API void AL_APIENTRY alFontsoundModulatoriSOFT(ALuint id, ALsizei stage, ALenum param, ALint value)
449 ALCdevice *device;
450 ALCcontext *context;
451 ALfontsound *sound;
453 context = GetContextRef();
454 if(!context) return;
456 device = context->Device;
457 if(!(sound=LookupFontsound(device, id)))
458 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
459 ALfontsound_setModStagei(sound, context, stage, param, value);
461 done:
462 ALCcontext_DecRef(context);
465 AL_API void AL_APIENTRY alGetFontsoundModulatorivSOFT(ALuint id, ALsizei stage, ALenum param, ALint *values)
467 ALCdevice *device;
468 ALCcontext *context;
469 ALfontsound *sound;
471 context = GetContextRef();
472 if(!context) return;
474 device = context->Device;
475 if(!(sound=LookupFontsound(device, id)))
476 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
477 ALfontsound_getModStagei(sound, context, stage, param, values);
479 done:
480 ALCcontext_DecRef(context);
484 ALfontsound *NewFontsound(ALCcontext *context)
486 ALCdevice *device = context->Device;
487 ALfontsound *sound;
488 ALenum err;
490 sound = calloc(1, sizeof(*sound));
491 if(!sound)
492 SET_ERROR_AND_RETURN_VALUE(context, AL_OUT_OF_MEMORY, NULL);
493 ALfontsound_Construct(sound);
495 err = NewThunkEntry(&sound->id);
496 if(err == AL_NO_ERROR)
497 err = InsertUIntMapEntry(&device->FontsoundMap, sound->id, sound);
498 if(err != AL_NO_ERROR)
500 ALfontsound_Destruct(sound);
501 memset(sound, 0, sizeof(*sound));
502 free(sound);
504 SET_ERROR_AND_RETURN_VALUE(context, err, NULL);
507 return sound;
510 void DeleteFontsound(ALCdevice *device, ALfontsound *sound)
512 RemoveFontsound(device, sound->id);
514 ALfontsound_Destruct(sound);
516 memset(sound, 0, sizeof(*sound));
517 free(sound);
521 static void ALfontsound_Construct(ALfontsound *self)
523 InitRef(&self->ref, 0);
525 self->Buffer = NULL;
527 self->MinKey = 0;
528 self->MaxKey = 127;
529 self->MinVelocity = 0;
530 self->MaxVelocity = 127;
532 self->ModLfoToPitch = 0;
533 self->VibratoLfoToPitch = 0;
534 self->ModEnvToPitch = 0;
536 self->FilterCutoff = 13500;
537 self->FilterQ = 0;
538 self->ModLfoToFilterCutoff = 0;
539 self->ModEnvToFilterCutoff = 0;
540 self->ModLfoToVolume = 0;
542 self->ChorusSend = 0;
543 self->ReverbSend = 0;
545 self->Pan = 0;
547 self->ModLfo.Delay = 0;
548 self->ModLfo.Frequency = 0;
550 self->VibratoLfo.Delay = 0;
551 self->VibratoLfo.Frequency = 0;
553 self->ModEnv.DelayTime = -12000;
554 self->ModEnv.AttackTime = -12000;
555 self->ModEnv.HoldTime = -12000;
556 self->ModEnv.DecayTime = -12000;
557 self->ModEnv.SustainAttn = 0;
558 self->ModEnv.ReleaseTime = -12000;
559 self->ModEnv.KeyToHoldTime = 0;
560 self->ModEnv.KeyToDecayTime = 0;
562 self->VolEnv.DelayTime = -12000;
563 self->VolEnv.AttackTime = -12000;
564 self->VolEnv.HoldTime = -12000;
565 self->VolEnv.DecayTime = -12000;
566 self->VolEnv.SustainAttn = 0;
567 self->VolEnv.ReleaseTime = -12000;
568 self->VolEnv.KeyToHoldTime = 0;
569 self->VolEnv.KeyToDecayTime = 0;
571 self->Attenuation = 0;
573 self->CoarseTuning = 0;
574 self->FineTuning = 0;
576 self->LoopMode = AL_NONE;
578 self->TuningScale = 100;
580 self->ExclusiveClass = 0;
582 self->Start = 0;
583 self->End = 0;
584 self->LoopStart = 0;
585 self->LoopEnd = 0;
586 self->SampleRate = 0;
587 self->PitchKey = 0;
588 self->PitchCorrection = 0;
589 self->SampleType = AL_MONO_SOFT;
590 self->Link = NULL;
592 InitUIntMap(&self->ModulatorMap, ~0);
594 self->id = 0;
597 static void ALfontsound_Destruct(ALfontsound *self)
599 ALsizei i;
601 FreeThunkEntry(self->id);
602 self->id = 0;
604 if(self->Buffer)
605 DecrementRef(&self->Buffer->ref);
606 self->Buffer = NULL;
607 if(self->Link)
608 DecrementRef(&self->Link->ref);
609 self->Link = NULL;
611 for(i = 0;i < self->ModulatorMap.size;i++)
613 free(self->ModulatorMap.array[i].value);
614 self->ModulatorMap.array[i].value = NULL;
616 ResetUIntMap(&self->ModulatorMap);
619 void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, ALint value)
621 ALfontsound *link;
622 ALbuffer *buffer;
624 switch(param)
626 case AL_BUFFER:
627 buffer = value ? LookupBuffer(context->Device, value) : NULL;
628 if(value && !buffer)
629 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
630 else if(buffer)
632 /* Buffer must have a non-0 length, and must be mono. */
633 if(buffer->SampleLen <= 0 || buffer->FmtChannels != FmtMono)
634 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
637 if(buffer) IncrementRef(&buffer->ref);
638 if((buffer=ExchangePtr((XchgPtr*)&self->Buffer, buffer)) != NULL)
639 DecrementRef(&buffer->ref);
640 break;
642 case AL_MOD_LFO_TO_PITCH_SOFT:
643 self->ModLfoToPitch = value;
644 break;
646 case AL_VIBRATO_LFO_TO_PITCH_SOFT:
647 self->VibratoLfoToPitch = value;
648 break;
650 case AL_MOD_ENV_TO_PITCH_SOFT:
651 self->ModEnvToPitch = value;
652 break;
654 case AL_FILTER_CUTOFF_SOFT:
655 self->FilterCutoff = value;
656 break;
658 case AL_FILTER_RESONANCE_SOFT:
659 if(!(value >= 0))
660 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
661 self->FilterQ = value;
662 break;
664 case AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT:
665 self->ModLfoToFilterCutoff = value;
666 break;
668 case AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT:
669 self->ModEnvToFilterCutoff = value;
670 break;
672 case AL_MOD_LFO_TO_VOLUME_SOFT:
673 self->ModLfoToVolume = value;
674 break;
676 case AL_CHORUS_SEND_SOFT:
677 if(!(value >= 0 && value <= 1000))
678 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
679 self->ChorusSend = value;
680 break;
681 case AL_REVERB_SEND_SOFT:
682 if(!(value >= 0 && value <= 1000))
683 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
684 self->ReverbSend = value;
685 break;
687 case AL_PAN_SOFT:
688 self->Pan = value;
689 break;
691 case AL_MOD_LFO_DELAY_SOFT:
692 self->ModLfo.Delay = value;
693 break;
694 case AL_MOD_LFO_FREQUENCY_SOFT:
695 self->ModLfo.Frequency = value;
696 break;
698 case AL_VIBRATO_LFO_DELAY_SOFT:
699 self->VibratoLfo.Delay = value;
700 break;
701 case AL_VIBRATO_LFO_FREQUENCY_SOFT:
702 self->VibratoLfo.Frequency = value;
703 break;
705 case AL_MOD_ENV_DELAYTIME_SOFT:
706 self->ModEnv.DelayTime = value;
707 break;
708 case AL_MOD_ENV_ATTACKTIME_SOFT:
709 self->ModEnv.AttackTime = value;
710 break;
711 case AL_MOD_ENV_HOLDTIME_SOFT:
712 self->ModEnv.HoldTime = value;
713 break;
714 case AL_MOD_ENV_DECAYTIME_SOFT:
715 self->ModEnv.DecayTime = value;
716 break;
717 case AL_MOD_ENV_SUSTAINVOLUME_SOFT:
718 self->ModEnv.SustainAttn = value;
719 break;
720 case AL_MOD_ENV_RELEASETIME_SOFT:
721 self->ModEnv.ReleaseTime = value;
722 break;
723 case AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT:
724 self->ModEnv.KeyToHoldTime = value;
725 break;
726 case AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT:
727 self->ModEnv.KeyToDecayTime = value;
728 break;
730 case AL_VOLUME_ENV_DELAYTIME_SOFT:
731 self->VolEnv.DelayTime = value;
732 break;
733 case AL_VOLUME_ENV_ATTACKTIME_SOFT:
734 self->VolEnv.AttackTime = value;
735 break;
736 case AL_VOLUME_ENV_HOLDTIME_SOFT:
737 self->VolEnv.HoldTime = value;
738 break;
739 case AL_VOLUME_ENV_DECAYTIME_SOFT:
740 self->VolEnv.DecayTime = value;
741 break;
742 case AL_VOLUME_ENV_SUSTAINVOLUME_SOFT:
743 self->VolEnv.SustainAttn = value;
744 break;
745 case AL_VOLUME_ENV_RELEASETIME_SOFT:
746 self->VolEnv.ReleaseTime = value;
747 break;
748 case AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT:
749 self->VolEnv.KeyToHoldTime = value;
750 break;
751 case AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT:
752 self->VolEnv.KeyToDecayTime = value;
753 break;
755 case AL_ATTENUATION_SOFT:
756 if(!(value >= 0))
757 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
758 self->Attenuation = value;
759 break;
761 case AL_TUNING_COARSE_SOFT:
762 self->CoarseTuning = value;
763 break;
764 case AL_TUNING_FINE_SOFT:
765 self->FineTuning = value;
766 break;
768 case AL_LOOP_MODE_SOFT:
769 if(!(value == AL_NONE || value == AL_LOOP_CONTINUOUS_SOFT ||
770 value == AL_LOOP_UNTIL_RELEASE_SOFT))
771 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
772 self->LoopMode = value;
773 break;
775 case AL_TUNING_SCALE_SOFT:
776 self->TuningScale = value;
777 break;
779 case AL_EXCLUSIVE_CLASS_SOFT:
780 self->ExclusiveClass = value;
781 break;
783 case AL_SAMPLE_START_SOFT:
784 self->Start = value;
785 break;
787 case AL_SAMPLE_END_SOFT:
788 self->End = value;
789 break;
791 case AL_SAMPLE_LOOP_START_SOFT:
792 self->LoopStart = value;
793 break;
795 case AL_SAMPLE_LOOP_END_SOFT:
796 self->LoopEnd = value;
797 break;
799 case AL_SAMPLE_RATE_SOFT:
800 if(!(value > 0))
801 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
802 self->SampleRate = value;
803 break;
805 case AL_BASE_KEY_SOFT:
806 if(!((value >= 0 && value <= 127) || value == 255))
807 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
808 self->PitchKey = value;
809 break;
811 case AL_KEY_CORRECTION_SOFT:
812 if(!(value >= -99 && value <= 99))
813 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
814 self->PitchCorrection = value;
815 break;
817 case AL_SAMPLE_TYPE_SOFT:
818 if(!(value == AL_MONO_SOFT || value == AL_RIGHT_SOFT || value == AL_LEFT_SOFT))
819 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
820 self->SampleType = value;
821 break;
823 case AL_FONTSOUND_LINK_SOFT:
824 link = value ? LookupFontsound(context->Device, value) : NULL;
825 if(value && !link)
826 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
828 if(link) IncrementRef(&link->ref);
829 if((link=ExchangePtr((XchgPtr*)&self->Link, link)) != NULL)
830 DecrementRef(&link->ref);
831 break;
833 default:
834 SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
838 static ALsfmodulator *ALfontsound_getModStage(ALfontsound *self, ALsizei stage)
840 ALsfmodulator *ret = LookupModulator(self, stage);
841 if(!ret)
843 static const ALsfmodulator moddef = {
844 { { AL_ONE_SOFT, AL_UNORM_SOFT, AL_LINEAR_SOFT },
845 { AL_ONE_SOFT, AL_UNORM_SOFT, AL_LINEAR_SOFT }
848 AL_LINEAR_SOFT,
849 AL_NONE
851 ret = malloc(sizeof(*ret));
852 *ret = moddef;
853 InsertUIntMapEntry(&self->ModulatorMap, stage, ret);
855 return ret;
858 void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint value)
860 ALint srcidx = 0;
862 if(ReadRef(&self->ref) != 0)
863 SET_ERROR_AND_RETURN(context, AL_INVALID_OPERATION);
864 switch(param)
866 case AL_SOURCE1_INPUT_SOFT:
867 srcidx++;
868 /* fall-through */
869 case AL_SOURCE0_INPUT_SOFT:
870 if(!(value == AL_ONE_SOFT || value == AL_NOTEON_VELOCITY_SOFT ||
871 value == AL_NOTEON_KEY_SOFT || value == AL_KEYPRESSURE_SOFT ||
872 value == AL_CHANNELPRESSURE_SOFT || value == AL_PITCHBEND_SOFT ||
873 value == AL_PITCHBEND_SENSITIVITY_SOFT ||
874 (value > 0 && value < 120 && !(value == 6 || (value >= 32 && value <= 63) ||
875 (value >= 98 && value <= 101))
878 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
879 ALfontsound_getModStage(self, stage)->Source[srcidx].Input = value;
880 break;
882 case AL_SOURCE1_TYPE_SOFT:
883 srcidx++;
884 /* fall-through */
885 case AL_SOURCE0_TYPE_SOFT:
886 if(!(value == AL_UNORM_SOFT || value == AL_UNORM_REV_SOFT ||
887 value == AL_SNORM_SOFT || value == AL_SNORM_REV_SOFT))
888 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
889 ALfontsound_getModStage(self, stage)->Source[srcidx].Type = value;
890 break;
892 case AL_SOURCE1_FORM_SOFT:
893 srcidx++;
894 /* fall-through */
895 case AL_SOURCE0_FORM_SOFT:
896 if(!(value == AL_LINEAR_SOFT || value == AL_CONCAVE_SOFT ||
897 value == AL_CONVEX_SOFT || value == AL_SWITCH_SOFT))
898 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
899 ALfontsound_getModStage(self, stage)->Source[srcidx].Form = value;
900 break;
902 case AL_AMOUNT_SOFT:
903 ALfontsound_getModStage(self, stage)->Amount = value;
904 break;
906 case AL_TRANSFORM_OP_SOFT:
907 if(!(value == AL_LINEAR_SOFT || value == AL_ABSOLUTE_SOFT))
908 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
909 ALfontsound_getModStage(self, stage)->TransformOp = value;
910 break;
912 case AL_DESTINATION_SOFT:
913 if(!(value == AL_MOD_LFO_TO_PITCH_SOFT || value == AL_VIBRATO_LFO_TO_PITCH_SOFT ||
914 value == AL_MOD_ENV_TO_PITCH_SOFT || value == AL_FILTER_CUTOFF_SOFT ||
915 value == AL_FILTER_RESONANCE_SOFT || value == AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT ||
916 value == AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT || value == AL_MOD_LFO_TO_VOLUME_SOFT ||
917 value == AL_CHORUS_SEND_SOFT || value == AL_REVERB_SEND_SOFT || value == AL_PAN_SOFT ||
918 value == AL_MOD_LFO_DELAY_SOFT || value == AL_MOD_LFO_FREQUENCY_SOFT ||
919 value == AL_VIBRATO_LFO_DELAY_SOFT || value == AL_VIBRATO_LFO_FREQUENCY_SOFT ||
920 value == AL_MOD_ENV_DELAYTIME_SOFT || value == AL_MOD_ENV_ATTACKTIME_SOFT ||
921 value == AL_MOD_ENV_HOLDTIME_SOFT || value == AL_MOD_ENV_DECAYTIME_SOFT ||
922 value == AL_MOD_ENV_SUSTAINVOLUME_SOFT || value == AL_MOD_ENV_RELEASETIME_SOFT ||
923 value == AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT || value == AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT ||
924 value == AL_VOLUME_ENV_DELAYTIME_SOFT || value == AL_VOLUME_ENV_ATTACKTIME_SOFT ||
925 value == AL_VOLUME_ENV_HOLDTIME_SOFT || value == AL_VOLUME_ENV_DECAYTIME_SOFT ||
926 value == AL_VOLUME_ENV_SUSTAINVOLUME_SOFT || value == AL_VOLUME_ENV_RELEASETIME_SOFT ||
927 value == AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT || value == AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT ||
928 value == AL_ATTENUATION_SOFT || value == AL_TUNING_COARSE_SOFT ||
929 value == AL_TUNING_FINE_SOFT || value == AL_TUNING_SCALE_SOFT))
930 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
931 ALfontsound_getModStage(self, stage)->Dest = value;
932 break;
934 default:
935 SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
939 static void ALfontsound_getModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint *values)
941 ALsfmodulator *mod = LookupModulator(self, stage);
942 ALint srcidx = 0;
944 switch(param)
946 case AL_SOURCE1_INPUT_SOFT:
947 srcidx++;
948 /* fall-through */
949 case AL_SOURCE0_INPUT_SOFT:
950 values[0] = mod ? mod->Source[srcidx].Input : AL_ONE_SOFT;
951 break;
953 case AL_SOURCE1_TYPE_SOFT:
954 srcidx++;
955 /* fall-through */
956 case AL_SOURCE0_TYPE_SOFT:
957 values[0] = mod ? mod->Source[srcidx].Type : AL_UNORM_SOFT;
958 break;
960 case AL_SOURCE1_FORM_SOFT:
961 srcidx++;
962 /* fall-through */
963 case AL_SOURCE0_FORM_SOFT:
964 values[0] = mod ? mod->Source[srcidx].Form : AL_LINEAR_SOFT;
965 break;
967 case AL_AMOUNT_SOFT:
968 values[0] = mod ? mod->Amount : 0;
969 break;
971 case AL_TRANSFORM_OP_SOFT:
972 values[0] = mod ? mod->TransformOp : AL_LINEAR_SOFT;
973 break;
975 case AL_DESTINATION_SOFT:
976 values[0] = mod ? mod->Dest : AL_NONE;
977 break;
979 default:
980 SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
985 /* ReleaseALFontsounds
987 * Called to destroy any fontsounds that still exist on the device
989 void ReleaseALFontsounds(ALCdevice *device)
991 ALsizei i;
992 for(i = 0;i < device->FontsoundMap.size;i++)
994 ALfontsound *temp = device->FontsoundMap.array[i].value;
995 device->FontsoundMap.array[i].value = NULL;
997 ALfontsound_Destruct(temp);
999 memset(temp, 0, sizeof(*temp));
1000 free(temp);