Allow "deleting" the default soundfont
The ID remains valid and the soundfont will be reloaded as needed, but this provides a way for the application to clear up the soundfont memory.
This commit is contained in:
parent
bb54743425
commit
540a99e71f
49
Alc/ALc.c
49
Alc/ALc.c
@ -1950,54 +1950,7 @@ static ALCvoid FreeDevice(ALCdevice *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(device->DefaultSfont)
|
if(device->DefaultSfont)
|
||||||
{
|
MidiSynth_deleteSoundfont(device, device->DefaultSfont);
|
||||||
ALsoundfont *sfont = device->DefaultSfont;
|
|
||||||
ALsfpreset **presets;
|
|
||||||
ALsizei num_presets;
|
|
||||||
ALsizei i;
|
|
||||||
|
|
||||||
presets = ExchangePtr((XchgPtr*)&sfont->Presets, NULL);
|
|
||||||
num_presets = ExchangeInt(&sfont->NumPresets, 0);
|
|
||||||
|
|
||||||
for(i = 0;i < num_presets;i++)
|
|
||||||
{
|
|
||||||
ALsfpreset *preset = presets[i];
|
|
||||||
ALfontsound **sounds;
|
|
||||||
ALsizei num_sounds;
|
|
||||||
ALboolean deleting;
|
|
||||||
ALsizei j;
|
|
||||||
|
|
||||||
sounds = ExchangePtr((XchgPtr*)&preset->Sounds, NULL);
|
|
||||||
num_sounds = ExchangeInt(&preset->NumSounds, 0);
|
|
||||||
DeletePreset(preset, device);
|
|
||||||
preset = NULL;
|
|
||||||
|
|
||||||
for(j = 0;j < num_sounds;j++)
|
|
||||||
DecrementRef(&sounds[j]->ref);
|
|
||||||
/* Some fontsounds may not be immediately deletable because they're
|
|
||||||
* linked to another fontsound. When those fontsounds are deleted
|
|
||||||
* they should become deletable, so use a loop until all fontsounds
|
|
||||||
* are deleted. */
|
|
||||||
do {
|
|
||||||
deleting = AL_FALSE;
|
|
||||||
for(j = 0;j < num_sounds;j++)
|
|
||||||
{
|
|
||||||
if(sounds[j] && sounds[j]->ref == 0)
|
|
||||||
{
|
|
||||||
deleting = AL_TRUE;
|
|
||||||
RemoveFontsound(device, sounds[j]->id);
|
|
||||||
ALfontsound_Destruct(sounds[j]);
|
|
||||||
free(sounds[j]);
|
|
||||||
sounds[j] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while(deleting);
|
|
||||||
free(sounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
ALsoundfont_Destruct(sfont);
|
|
||||||
free(sfont);
|
|
||||||
}
|
|
||||||
device->DefaultSfont = NULL;
|
device->DefaultSfont = NULL;
|
||||||
|
|
||||||
if(device->BufferMap.size > 0)
|
if(device->BufferMap.size > 0)
|
||||||
|
@ -188,6 +188,55 @@ ALsoundfont *MidiSynth_getDefSoundfont(ALCcontext *context)
|
|||||||
return device->DefaultSfont;
|
return device->DefaultSfont;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MidiSynth_deleteSoundfont(ALCdevice *device, ALsoundfont *sfont)
|
||||||
|
{
|
||||||
|
ALsfpreset **presets;
|
||||||
|
ALsizei num_presets;
|
||||||
|
ALsizei i;
|
||||||
|
|
||||||
|
presets = ExchangePtr((XchgPtr*)&sfont->Presets, NULL);
|
||||||
|
num_presets = ExchangeInt(&sfont->NumPresets, 0);
|
||||||
|
|
||||||
|
for(i = 0;i < num_presets;i++)
|
||||||
|
{
|
||||||
|
ALsfpreset *preset = presets[i];
|
||||||
|
ALfontsound **sounds;
|
||||||
|
ALsizei num_sounds;
|
||||||
|
ALboolean deleting;
|
||||||
|
ALsizei j;
|
||||||
|
|
||||||
|
sounds = ExchangePtr((XchgPtr*)&preset->Sounds, NULL);
|
||||||
|
num_sounds = ExchangeInt(&preset->NumSounds, 0);
|
||||||
|
DeletePreset(preset, device);
|
||||||
|
preset = NULL;
|
||||||
|
|
||||||
|
for(j = 0;j < num_sounds;j++)
|
||||||
|
DecrementRef(&sounds[j]->ref);
|
||||||
|
/* Some fontsounds may not be immediately deletable because they're
|
||||||
|
* linked to another fontsound. When those fontsounds are deleted
|
||||||
|
* they should become deletable, so use a loop until all fontsounds
|
||||||
|
* are deleted. */
|
||||||
|
do {
|
||||||
|
deleting = AL_FALSE;
|
||||||
|
for(j = 0;j < num_sounds;j++)
|
||||||
|
{
|
||||||
|
if(sounds[j] && sounds[j]->ref == 0)
|
||||||
|
{
|
||||||
|
deleting = AL_TRUE;
|
||||||
|
RemoveFontsound(device, sounds[j]->id);
|
||||||
|
ALfontsound_Destruct(sounds[j]);
|
||||||
|
free(sounds[j]);
|
||||||
|
sounds[j] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while(deleting);
|
||||||
|
free(sounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALsoundfont_Destruct(sfont);
|
||||||
|
free(sfont);
|
||||||
|
}
|
||||||
|
|
||||||
ALenum MidiSynth_selectSoundfonts(MidiSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids)
|
ALenum MidiSynth_selectSoundfonts(MidiSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids)
|
||||||
{
|
{
|
||||||
ALCdevice *device = context->Device;
|
ALCdevice *device = context->Device;
|
||||||
|
@ -53,6 +53,7 @@ typedef struct MidiSynth {
|
|||||||
void MidiSynth_Construct(MidiSynth *self, ALCdevice *device);
|
void MidiSynth_Construct(MidiSynth *self, ALCdevice *device);
|
||||||
void MidiSynth_Destruct(MidiSynth *self);
|
void MidiSynth_Destruct(MidiSynth *self);
|
||||||
struct ALsoundfont *MidiSynth_getDefSoundfont(ALCcontext *context);
|
struct ALsoundfont *MidiSynth_getDefSoundfont(ALCcontext *context);
|
||||||
|
void MidiSynth_deleteSoundfont(ALCdevice *device, struct ALsoundfont *sfont);
|
||||||
ALenum MidiSynth_selectSoundfonts(MidiSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids);
|
ALenum MidiSynth_selectSoundfonts(MidiSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids);
|
||||||
inline void MidiSynth_setGain(MidiSynth *self, ALfloat gain) { self->Gain = gain; }
|
inline void MidiSynth_setGain(MidiSynth *self, ALfloat gain) { self->Gain = gain; }
|
||||||
inline ALfloat MidiSynth_getGain(const MidiSynth *self) { return self->Gain; }
|
inline ALfloat MidiSynth_getGain(const MidiSynth *self) { return self->Gain; }
|
||||||
|
@ -76,11 +76,13 @@ AL_API ALvoid AL_APIENTRY alDeleteSoundfontsSOFT(ALsizei n, const ALuint *ids)
|
|||||||
device = context->Device;
|
device = context->Device;
|
||||||
for(i = 0;i < n;i++)
|
for(i = 0;i < n;i++)
|
||||||
{
|
{
|
||||||
if(!ids[i])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Check for valid soundfont ID */
|
/* Check for valid soundfont ID */
|
||||||
if((sfont=LookupSfont(device, ids[i])) == NULL)
|
if(ids[i] == 0)
|
||||||
|
{
|
||||||
|
if(!(sfont=device->DefaultSfont))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if((sfont=LookupSfont(device, ids[i])) == NULL)
|
||||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||||
if(sfont->Mapped != AL_FALSE || sfont->ref != 0)
|
if(sfont->Mapped != AL_FALSE || sfont->ref != 0)
|
||||||
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
|
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
|
||||||
@ -88,7 +90,17 @@ AL_API ALvoid AL_APIENTRY alDeleteSoundfontsSOFT(ALsizei n, const ALuint *ids)
|
|||||||
|
|
||||||
for(i = 0;i < n;i++)
|
for(i = 0;i < n;i++)
|
||||||
{
|
{
|
||||||
if((sfont=RemoveSfont(device, ids[i])) == NULL)
|
if(ids[i] == 0)
|
||||||
|
{
|
||||||
|
MidiSynth *synth = device->Synth;
|
||||||
|
WriteLock(&synth->Lock);
|
||||||
|
if(device->DefaultSfont != NULL)
|
||||||
|
MidiSynth_deleteSoundfont(device, device->DefaultSfont);
|
||||||
|
device->DefaultSfont = NULL;
|
||||||
|
WriteUnlock(&synth->Lock);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if((sfont=RemoveSfont(device, ids[i])) == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ALsoundfont_Destruct(sfont);
|
ALsoundfont_Destruct(sfont);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user