alPreset.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. #include "config.h"
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "alMain.h"
  5. #include "alMidi.h"
  6. #include "alError.h"
  7. #include "alThunk.h"
  8. #include "midi/base.h"
  9. extern inline struct ALsfpreset *LookupPreset(ALCdevice *device, ALuint id);
  10. extern inline struct ALsfpreset *RemovePreset(ALCdevice *device, ALuint id);
  11. static void ALsfpreset_Construct(ALsfpreset *self);
  12. void ALsfpreset_Destruct(ALsfpreset *self);
  13. AL_API void AL_APIENTRY alGenPresetsSOFT(ALsizei n, ALuint *ids)
  14. {
  15. ALCcontext *context;
  16. ALsizei cur = 0;
  17. context = GetContextRef();
  18. if(!context) return;
  19. if(!(n >= 0))
  20. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  21. for(cur = 0;cur < n;cur++)
  22. {
  23. ALsfpreset *preset = NewPreset(context);
  24. if(!preset)
  25. {
  26. alDeletePresetsSOFT(cur, ids);
  27. break;
  28. }
  29. ids[cur] = preset->id;
  30. }
  31. done:
  32. ALCcontext_DecRef(context);
  33. }
  34. AL_API ALvoid AL_APIENTRY alDeletePresetsSOFT(ALsizei n, const ALuint *ids)
  35. {
  36. ALCdevice *device;
  37. ALCcontext *context;
  38. ALsfpreset *preset;
  39. ALsizei i;
  40. context = GetContextRef();
  41. if(!context) return;
  42. if(!(n >= 0))
  43. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  44. device = context->Device;
  45. for(i = 0;i < n;i++)
  46. {
  47. /* Check for valid ID */
  48. if((preset=LookupPreset(device, ids[i])) == NULL)
  49. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  50. if(preset->ref != 0)
  51. SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
  52. }
  53. for(i = 0;i < n;i++)
  54. {
  55. if((preset=LookupPreset(device, ids[i])) == NULL)
  56. continue;
  57. DeletePreset(preset, device);
  58. }
  59. done:
  60. ALCcontext_DecRef(context);
  61. }
  62. AL_API ALboolean AL_APIENTRY alIsPresetSOFT(ALuint id)
  63. {
  64. ALCcontext *context;
  65. ALboolean ret;
  66. context = GetContextRef();
  67. if(!context) return AL_FALSE;
  68. ret = LookupPreset(context->Device, id) ? AL_TRUE : AL_FALSE;
  69. ALCcontext_DecRef(context);
  70. return ret;
  71. }
  72. AL_API void AL_APIENTRY alPresetiSOFT(ALuint id, ALenum param, ALint value)
  73. {
  74. ALCdevice *device;
  75. ALCcontext *context;
  76. ALsfpreset *preset;
  77. context = GetContextRef();
  78. if(!context) return;
  79. device = context->Device;
  80. if((preset=LookupPreset(device, id)) == NULL)
  81. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  82. if(preset->ref != 0)
  83. SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
  84. switch(param)
  85. {
  86. case AL_MIDI_PRESET_SOFT:
  87. if(!(value >= 0 && value <= 127))
  88. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  89. preset->Preset = value;
  90. break;
  91. case AL_MIDI_BANK_SOFT:
  92. if(!(value >= 0 && value <= 128))
  93. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  94. preset->Bank = value;
  95. break;
  96. default:
  97. SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
  98. }
  99. done:
  100. ALCcontext_DecRef(context);
  101. }
  102. AL_API void AL_APIENTRY alPresetivSOFT(ALuint id, ALenum param, const ALint *values)
  103. {
  104. ALCdevice *device;
  105. ALCcontext *context;
  106. ALsfpreset *preset;
  107. switch(param)
  108. {
  109. case AL_MIDI_PRESET_SOFT:
  110. case AL_MIDI_BANK_SOFT:
  111. alPresetiSOFT(id, param, values[0]);
  112. return;
  113. }
  114. context = GetContextRef();
  115. if(!context) return;
  116. device = context->Device;
  117. if((preset=LookupPreset(device, id)) == NULL)
  118. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  119. if(preset->ref != 0)
  120. SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
  121. switch(param)
  122. {
  123. default:
  124. SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
  125. }
  126. done:
  127. ALCcontext_DecRef(context);
  128. }
  129. AL_API void AL_APIENTRY alGetPresetivSOFT(ALuint id, ALenum param, ALint *values)
  130. {
  131. ALCdevice *device;
  132. ALCcontext *context;
  133. ALsfpreset *preset;
  134. ALsizei i;
  135. context = GetContextRef();
  136. if(!context) return;
  137. device = context->Device;
  138. if((preset=LookupPreset(device, id)) == NULL)
  139. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  140. switch(param)
  141. {
  142. case AL_MIDI_PRESET_SOFT:
  143. values[0] = preset->Preset;
  144. break;
  145. case AL_MIDI_BANK_SOFT:
  146. values[0] = preset->Bank;
  147. break;
  148. case AL_FONTSOUNDS_SIZE_SOFT:
  149. values[0] = preset->NumSounds;
  150. break;
  151. case AL_FONTSOUNDS_SOFT:
  152. for(i = 0;i < preset->NumSounds;i++)
  153. values[i] = preset->Sounds[i]->id;
  154. break;
  155. default:
  156. SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
  157. }
  158. done:
  159. ALCcontext_DecRef(context);
  160. }
  161. AL_API void AL_APIENTRY alPresetFontsoundsSOFT(ALuint id, ALsizei count, const ALuint *fsids)
  162. {
  163. ALCdevice *device;
  164. ALCcontext *context;
  165. ALsfpreset *preset;
  166. ALfontsound **sounds;
  167. ALsizei i;
  168. context = GetContextRef();
  169. if(!context) return;
  170. device = context->Device;
  171. if(!(preset=LookupPreset(device, id)))
  172. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  173. if(count < 0)
  174. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  175. if(preset->ref != 0)
  176. SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
  177. if(count == 0)
  178. sounds = NULL;
  179. else
  180. {
  181. sounds = calloc(count, sizeof(sounds[0]));
  182. if(!sounds)
  183. SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
  184. for(i = 0;i < count;i++)
  185. {
  186. if(!(sounds[i]=LookupFontsound(device, fsids[i])))
  187. {
  188. free(sounds);
  189. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  190. }
  191. }
  192. }
  193. for(i = 0;i < count;i++)
  194. IncrementRef(&sounds[i]->ref);
  195. sounds = ExchangePtr((XchgPtr*)&preset->Sounds, sounds);
  196. count = ExchangeInt(&preset->NumSounds, count);
  197. for(i = 0;i < count;i++)
  198. DecrementRef(&sounds[i]->ref);
  199. free(sounds);
  200. done:
  201. ALCcontext_DecRef(context);
  202. }
  203. ALsfpreset *NewPreset(ALCcontext *context)
  204. {
  205. ALCdevice *device = context->Device;
  206. ALsfpreset *preset;
  207. ALenum err;
  208. preset = calloc(1, sizeof(*preset));
  209. if(!preset)
  210. SET_ERROR_AND_RETURN_VALUE(context, AL_OUT_OF_MEMORY, NULL);
  211. ALsfpreset_Construct(preset);
  212. err = NewThunkEntry(&preset->id);
  213. if(err == AL_NO_ERROR)
  214. err = InsertUIntMapEntry(&device->PresetMap, preset->id, preset);
  215. if(err != AL_NO_ERROR)
  216. {
  217. ALsfpreset_Destruct(preset);
  218. memset(preset, 0, sizeof(*preset));
  219. free(preset);
  220. SET_ERROR_AND_RETURN_VALUE(context, err, NULL);
  221. }
  222. return preset;
  223. }
  224. void DeletePreset(ALsfpreset *preset, ALCdevice *device)
  225. {
  226. RemovePreset(device, preset->id);
  227. ALsfpreset_Destruct(preset);
  228. memset(preset, 0, sizeof(*preset));
  229. free(preset);
  230. }
  231. static void ALsfpreset_Construct(ALsfpreset *self)
  232. {
  233. self->ref = 0;
  234. self->Preset = 0;
  235. self->Bank = 0;
  236. self->Sounds = NULL;
  237. self->NumSounds = 0;
  238. self->id = 0;
  239. }
  240. void ALsfpreset_Destruct(ALsfpreset *self)
  241. {
  242. ALsizei i;
  243. FreeThunkEntry(self->id);
  244. self->id = 0;
  245. for(i = 0;i < self->NumSounds;i++)
  246. DecrementRef(&self->Sounds[i]->ref);
  247. free(self->Sounds);
  248. self->Sounds = NULL;
  249. self->NumSounds = 0;
  250. }
  251. /* ReleaseALPresets
  252. *
  253. * Called to destroy any presets that still exist on the device
  254. */
  255. void ReleaseALPresets(ALCdevice *device)
  256. {
  257. ALsizei i;
  258. for(i = 0;i < device->PresetMap.size;i++)
  259. {
  260. ALsfpreset *temp = device->PresetMap.array[i].value;
  261. device->PresetMap.array[i].value = NULL;
  262. ALsfpreset_Destruct(temp);
  263. memset(temp, 0, sizeof(*temp));
  264. free(temp);
  265. }
  266. }