Move atomic method definitions to a separate common source
[openal-soft.git] / OpenAL32 / alPreset.c
blobd34772a41107b61168c8410a1a7fe8f87e6b5917
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"
12 #include "midi/base.h"
15 extern inline struct ALsfpreset *LookupPreset(ALCdevice *device, ALuint id);
16 extern inline struct ALsfpreset *RemovePreset(ALCdevice *device, ALuint id);
18 static void ALsfpreset_Construct(ALsfpreset *self);
19 void ALsfpreset_Destruct(ALsfpreset *self);
22 AL_API void AL_APIENTRY alGenPresetsSOFT(ALsizei n, ALuint *ids)
24 ALCcontext *context;
25 ALsizei cur = 0;
27 context = GetContextRef();
28 if(!context) return;
30 if(!(n >= 0))
31 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
33 for(cur = 0;cur < n;cur++)
35 ALsfpreset *preset = NewPreset(context);
36 if(!preset)
38 alDeletePresetsSOFT(cur, ids);
39 break;
42 ids[cur] = preset->id;
45 done:
46 ALCcontext_DecRef(context);
49 AL_API ALvoid AL_APIENTRY alDeletePresetsSOFT(ALsizei n, const ALuint *ids)
51 ALCdevice *device;
52 ALCcontext *context;
53 ALsfpreset *preset;
54 ALsizei i;
56 context = GetContextRef();
57 if(!context) return;
59 if(!(n >= 0))
60 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
62 device = context->Device;
63 for(i = 0;i < n;i++)
65 /* Check for valid ID */
66 if((preset=LookupPreset(device, ids[i])) == NULL)
67 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
68 if(preset->ref != 0)
69 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
72 for(i = 0;i < n;i++)
74 if((preset=LookupPreset(device, ids[i])) == NULL)
75 continue;
76 DeletePreset(preset, device);
79 done:
80 ALCcontext_DecRef(context);
83 AL_API ALboolean AL_APIENTRY alIsPresetSOFT(ALuint id)
85 ALCcontext *context;
86 ALboolean ret;
88 context = GetContextRef();
89 if(!context) return AL_FALSE;
91 ret = LookupPreset(context->Device, id) ? AL_TRUE : AL_FALSE;
93 ALCcontext_DecRef(context);
95 return ret;
98 AL_API void AL_APIENTRY alPresetiSOFT(ALuint id, ALenum param, ALint value)
100 ALCdevice *device;
101 ALCcontext *context;
102 ALsfpreset *preset;
104 context = GetContextRef();
105 if(!context) return;
107 device = context->Device;
108 if((preset=LookupPreset(device, id)) == NULL)
109 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
110 if(preset->ref != 0)
111 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
112 switch(param)
114 case AL_MIDI_PRESET_SOFT:
115 if(!(value >= 0 && value <= 127))
116 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
117 preset->Preset = value;
118 break;
120 case AL_MIDI_BANK_SOFT:
121 if(!(value >= 0 && value <= 128))
122 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
123 preset->Bank = value;
124 break;
126 default:
127 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
130 done:
131 ALCcontext_DecRef(context);
134 AL_API void AL_APIENTRY alPresetivSOFT(ALuint id, ALenum param, const ALint *values)
136 ALCdevice *device;
137 ALCcontext *context;
138 ALsfpreset *preset;
140 switch(param)
142 case AL_MIDI_PRESET_SOFT:
143 case AL_MIDI_BANK_SOFT:
144 alPresetiSOFT(id, param, values[0]);
145 return;
148 context = GetContextRef();
149 if(!context) return;
151 device = context->Device;
152 if((preset=LookupPreset(device, id)) == NULL)
153 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
154 if(preset->ref != 0)
155 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
156 switch(param)
158 default:
159 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
162 done:
163 ALCcontext_DecRef(context);
166 AL_API void AL_APIENTRY alGetPresetivSOFT(ALuint id, ALenum param, ALint *values)
168 ALCdevice *device;
169 ALCcontext *context;
170 ALsfpreset *preset;
171 ALsizei i;
173 context = GetContextRef();
174 if(!context) return;
176 device = context->Device;
177 if((preset=LookupPreset(device, id)) == NULL)
178 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
179 switch(param)
181 case AL_MIDI_PRESET_SOFT:
182 values[0] = preset->Preset;
183 break;
185 case AL_MIDI_BANK_SOFT:
186 values[0] = preset->Bank;
187 break;
189 case AL_FONTSOUNDS_SIZE_SOFT:
190 values[0] = preset->NumSounds;
191 break;
193 case AL_FONTSOUNDS_SOFT:
194 for(i = 0;i < preset->NumSounds;i++)
195 values[i] = preset->Sounds[i]->id;
196 break;
198 default:
199 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
202 done:
203 ALCcontext_DecRef(context);
206 AL_API void AL_APIENTRY alPresetFontsoundsSOFT(ALuint id, ALsizei count, const ALuint *fsids)
208 ALCdevice *device;
209 ALCcontext *context;
210 ALsfpreset *preset;
211 ALfontsound **sounds;
212 ALsizei i;
214 context = GetContextRef();
215 if(!context) return;
217 device = context->Device;
218 if(!(preset=LookupPreset(device, id)))
219 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
220 if(count < 0)
221 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
223 if(preset->ref != 0)
224 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
226 if(count == 0)
227 sounds = NULL;
228 else
230 sounds = calloc(count, sizeof(sounds[0]));
231 if(!sounds)
232 SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
234 for(i = 0;i < count;i++)
236 if(!(sounds[i]=LookupFontsound(device, fsids[i])))
238 free(sounds);
239 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
244 for(i = 0;i < count;i++)
245 IncrementRef(&sounds[i]->ref);
247 sounds = ExchangePtr((XchgPtr*)&preset->Sounds, sounds);
248 count = ExchangeInt(&preset->NumSounds, count);
250 for(i = 0;i < count;i++)
251 DecrementRef(&sounds[i]->ref);
252 free(sounds);
254 done:
255 ALCcontext_DecRef(context);
259 ALsfpreset *NewPreset(ALCcontext *context)
261 ALCdevice *device = context->Device;
262 ALsfpreset *preset;
263 ALenum err;
265 preset = calloc(1, sizeof(*preset));
266 if(!preset)
267 SET_ERROR_AND_RETURN_VALUE(context, AL_OUT_OF_MEMORY, NULL);
268 ALsfpreset_Construct(preset);
270 err = NewThunkEntry(&preset->id);
271 if(err == AL_NO_ERROR)
272 err = InsertUIntMapEntry(&device->PresetMap, preset->id, preset);
273 if(err != AL_NO_ERROR)
275 ALsfpreset_Destruct(preset);
276 memset(preset, 0, sizeof(*preset));
277 free(preset);
279 SET_ERROR_AND_RETURN_VALUE(context, err, NULL);
282 return preset;
285 void DeletePreset(ALsfpreset *preset, ALCdevice *device)
287 RemovePreset(device, preset->id);
289 ALsfpreset_Destruct(preset);
290 memset(preset, 0, sizeof(*preset));
291 free(preset);
295 static void ALsfpreset_Construct(ALsfpreset *self)
297 self->ref = 0;
299 self->Preset = 0;
300 self->Bank = 0;
302 self->Sounds = NULL;
303 self->NumSounds = 0;
305 self->id = 0;
308 void ALsfpreset_Destruct(ALsfpreset *self)
310 ALsizei i;
312 FreeThunkEntry(self->id);
313 self->id = 0;
315 for(i = 0;i < self->NumSounds;i++)
316 DecrementRef(&self->Sounds[i]->ref);
317 free(self->Sounds);
318 self->Sounds = NULL;
319 self->NumSounds = 0;
323 /* ReleaseALPresets
325 * Called to destroy any presets that still exist on the device
327 void ReleaseALPresets(ALCdevice *device)
329 ALsizei i;
330 for(i = 0;i < device->PresetMap.size;i++)
332 ALsfpreset *temp = device->PresetMap.array[i].value;
333 device->PresetMap.array[i].value = NULL;
335 ALsfpreset_Destruct(temp);
337 memset(temp, 0, sizeof(*temp));
338 free(temp);