12 #include "midi/base.h"
15 extern inline struct ALsoundfont
*LookupSfont(ALCdevice
*device
, ALuint id
);
16 extern inline struct ALsoundfont
*RemoveSfont(ALCdevice
*device
, ALuint id
);
19 AL_API
void AL_APIENTRY
alGenSoundfontsSOFT(ALsizei n
, ALuint
*ids
)
26 context
= GetContextRef();
30 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
32 device
= context
->Device
;
33 for(cur
= 0;cur
< n
;cur
++)
35 ALsoundfont
*sfont
= calloc(1, sizeof(ALsoundfont
));
38 alDeleteSoundfontsSOFT(cur
, ids
);
39 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
41 ALsoundfont_Construct(sfont
);
43 err
= NewThunkEntry(&sfont
->id
);
44 if(err
== AL_NO_ERROR
)
45 err
= InsertUIntMapEntry(&device
->SfontMap
, sfont
->id
, sfont
);
46 if(err
!= AL_NO_ERROR
)
48 ALsoundfont_Destruct(sfont
);
49 memset(sfont
, 0, sizeof(ALsoundfont
));
52 alDeleteSoundfontsSOFT(cur
, ids
);
53 SET_ERROR_AND_GOTO(context
, err
, done
);
60 ALCcontext_DecRef(context
);
63 AL_API ALvoid AL_APIENTRY
alDeleteSoundfontsSOFT(ALsizei n
, const ALuint
*ids
)
70 context
= GetContextRef();
74 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
76 device
= context
->Device
;
82 /* Check for valid soundfont ID */
83 if((sfont
=LookupSfont(device
, ids
[i
])) == NULL
)
84 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
85 if(sfont
->Mapped
!= AL_FALSE
|| sfont
->ref
!= 0)
86 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
91 if((sfont
=RemoveSfont(device
, ids
[i
])) == NULL
)
94 ALsoundfont_Destruct(sfont
);
96 memset(sfont
, 0, sizeof(*sfont
));
101 ALCcontext_DecRef(context
);
104 AL_API ALboolean AL_APIENTRY
alIsSoundfontSOFT(ALuint id
)
109 context
= GetContextRef();
110 if(!context
) return AL_FALSE
;
112 ret
= ((!id
|| LookupSfont(context
->Device
, id
)) ?
115 ALCcontext_DecRef(context
);
120 AL_API ALvoid AL_APIENTRY
alSoundfontSamplesSOFT(ALuint sfid
, ALenum type
, ALsizei count
, const ALvoid
*samples
)
127 context
= GetContextRef();
130 device
= context
->Device
;
131 if(!(sfont
=LookupSfont(device
, sfid
)))
132 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
133 if(type
!= AL_SHORT_SOFT
)
134 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
136 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
138 WriteLock(&sfont
->Lock
);
140 alSetError(context
, AL_INVALID_OPERATION
);
141 else if(sfont
->Mapped
)
142 alSetError(context
, AL_INVALID_OPERATION
);
143 else if(!(ptr
=realloc(sfont
->Samples
, count
* sizeof(ALshort
))))
144 alSetError(context
, AL_OUT_OF_MEMORY
);
147 sfont
->Samples
= ptr
;
148 sfont
->NumSamples
= count
;
150 memcpy(sfont
->Samples
, samples
, count
* sizeof(ALshort
));
152 WriteUnlock(&sfont
->Lock
);
155 ALCcontext_DecRef(context
);
158 AL_API ALvoid
* AL_APIENTRY
alSoundfontMapSamplesSOFT(ALuint sfid
, ALsizei offset
, ALsizei length
)
165 context
= GetContextRef();
166 if(!context
) return NULL
;
168 device
= context
->Device
;
169 if(!(sfont
=LookupSfont(device
, sfid
)))
170 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
171 if(offset
< 0 || (ALuint
)offset
> sfont
->NumSamples
*sizeof(ALshort
))
172 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
173 if(length
<= 0 || (ALuint
)length
> (sfont
->NumSamples
*sizeof(ALshort
) - offset
))
174 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
176 ReadLock(&sfont
->Lock
);
178 alSetError(context
, AL_INVALID_OPERATION
);
179 else if(ExchangeInt(&sfont
->Mapped
, AL_TRUE
) == AL_TRUE
)
180 alSetError(context
, AL_INVALID_OPERATION
);
182 ptr
= (ALbyte
*)sfont
->Samples
+ offset
;
183 ReadUnlock(&sfont
->Lock
);
186 ALCcontext_DecRef(context
);
191 AL_API ALvoid AL_APIENTRY
alSoundfontUnmapSamplesSOFT(ALuint sfid
)
197 context
= GetContextRef();
200 device
= context
->Device
;
201 if(!(sfont
=LookupSfont(device
, sfid
)))
202 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
203 if(ExchangeInt(&sfont
->Mapped
, AL_FALSE
) == AL_FALSE
)
204 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
207 ALCcontext_DecRef(context
);
210 AL_API
void AL_APIENTRY
alGetSoundfontivSOFT(ALuint id
, ALenum param
, ALint
*values
)
217 context
= GetContextRef();
220 device
= context
->Device
;
221 if(!(sfont
=LookupSfont(device
, id
)))
222 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
225 case AL_PRESETS_SIZE_SOFT
:
226 values
[0] = sfont
->NumPresets
;
229 case AL_PRESETS_SOFT
:
230 for(i
= 0;i
< sfont
->NumPresets
;i
++)
231 values
[i
] = sfont
->Presets
[i
]->id
;
234 case AL_SAMPLE_LENGTH_SOFT
:
235 values
[0] = sfont
->NumSamples
;
238 case AL_FORMAT_TYPE_SOFT
:
239 values
[0] = AL_SHORT_SOFT
;
243 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
247 ALCcontext_DecRef(context
);
250 AL_API
void AL_APIENTRY
alSoundfontPresetsSOFT(ALuint id
, ALsizei count
, const ALuint
*pids
)
255 ALsfpreset
**presets
;
258 context
= GetContextRef();
261 device
= context
->Device
;
262 if(!(sfont
=LookupSfont(device
, id
)))
263 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
265 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
267 WriteLock(&sfont
->Lock
);
270 WriteUnlock(&sfont
->Lock
);
271 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
278 presets
= calloc(count
, sizeof(presets
[0]));
281 WriteUnlock(&sfont
->Lock
);
282 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
285 for(i
= 0;i
< count
;i
++)
287 if(!(presets
[i
]=LookupPreset(device
, pids
[i
])))
289 WriteUnlock(&sfont
->Lock
);
290 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
295 for(i
= 0;i
< count
;i
++)
296 IncrementRef(&presets
[i
]->ref
);
298 presets
= ExchangePtr((XchgPtr
*)&sfont
->Presets
, presets
);
299 count
= ExchangeInt(&sfont
->NumPresets
, count
);
300 WriteUnlock(&sfont
->Lock
);
302 for(i
= 0;i
< count
;i
++)
303 DecrementRef(&presets
[i
]->ref
);
307 ALCcontext_DecRef(context
);
311 /* ReleaseALSoundfonts
313 * Called to destroy any soundfonts that still exist on the device
315 void ReleaseALSoundfonts(ALCdevice
*device
)
318 for(i
= 0;i
< device
->SfontMap
.size
;i
++)
320 ALsoundfont
*temp
= device
->SfontMap
.array
[i
].value
;
321 device
->SfontMap
.array
[i
].value
= NULL
;
323 ALsoundfont_Destruct(temp
);
325 memset(temp
, 0, sizeof(*temp
));