Module: wine Branch: master Commit: 157ffca64df4eb50f7444ba644467f9f62ddba4b URL: https://gitlab.winehq.org/wine/wine/-/commit/157ffca64df4eb50f7444ba644467f9...
Author: Anton Baskanov baskanov@gmail.com Date: Wed Nov 8 14:43:09 2023 +0700
dmsynth: Free the allocated presets manually.
FluidSynth never calls synth_preset_free(), causing preset and instrument leaks.
---
dlls/dmsynth/synth.c | 69 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 11 deletions(-)
diff --git a/dlls/dmsynth/synth.c b/dlls/dmsynth/synth.c index 6d747980cbd..b3c624b5b6b 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -319,6 +319,17 @@ static void instrument_release(struct instrument *instrument) } }
+struct preset +{ + struct list entry; + int bank; + int patch; + + fluid_preset_t *fluid_preset; + + struct instrument *instrument; +}; + struct event { struct list entry; @@ -350,6 +361,7 @@ struct synth struct list waves; struct list events; struct list voices; + struct list presets;
fluid_settings_t *fluid_settings; fluid_sfont_t *fluid_sfont; @@ -598,6 +610,7 @@ static HRESULT WINAPI synth_Open(IDirectMusicSynth8 *iface, DMUS_PORTPARAMS *par static HRESULT WINAPI synth_Close(IDirectMusicSynth8 *iface) { struct synth *This = impl_from_IDirectMusicSynth8(iface); + struct preset *preset; struct voice *voice; void *next;
@@ -621,6 +634,14 @@ static HRESULT WINAPI synth_Close(IDirectMusicSynth8 *iface) free(voice); }
+ LIST_FOR_EACH_ENTRY_SAFE(preset, next, &This->presets, struct preset, entry) + { + list_remove(&preset->entry); + instrument_release(preset->instrument); + delete_fluid_preset(preset->fluid_preset); + free(preset); + } + This->open = FALSE; LeaveCriticalSection(&This->cs);
@@ -1394,11 +1415,11 @@ static int synth_preset_get_bank(fluid_preset_t *fluid_preset)
static int synth_preset_get_num(fluid_preset_t *fluid_preset) { - struct instrument *instrument = fluid_preset_get_data(fluid_preset); + struct preset *preset = fluid_preset_get_data(fluid_preset);
TRACE("(%p)\n", fluid_preset);
- return instrument->patch; + return preset->patch; }
static BOOL gen_from_connection(const CONNECTION *conn, UINT *gen) @@ -1760,7 +1781,8 @@ static void set_default_voice_connections(fluid_voice_t *fluid_voice)
static int synth_preset_noteon(fluid_preset_t *fluid_preset, fluid_synth_t *fluid_synth, int chan, int key, int vel) { - struct instrument *instrument = fluid_preset_get_data(fluid_preset); + struct preset *preset = fluid_preset_get_data(fluid_preset); + struct instrument *instrument = preset->instrument; struct synth *synth = instrument->synth; fluid_voice_t *fluid_voice; struct region *region; @@ -1836,9 +1858,6 @@ static int synth_preset_noteon(fluid_preset_t *fluid_preset, fluid_synth_t *flui
static void synth_preset_free(fluid_preset_t *fluid_preset) { - struct instrument *instrument = fluid_preset_get_data(fluid_preset); - fluid_preset_set_data(fluid_preset, NULL); - if (instrument) instrument_release(instrument); }
static const char *synth_sfont_get_name(fluid_sfont_t *fluid_sfont) @@ -1851,11 +1870,21 @@ static fluid_preset_t *synth_sfont_get_preset(fluid_sfont_t *fluid_sfont, int ba struct synth *synth = fluid_sfont_get_data(fluid_sfont); struct instrument *instrument; fluid_preset_t *fluid_preset; + struct preset *preset;
TRACE("(%p, %d, %d)\n", fluid_sfont, bank, patch);
EnterCriticalSection(&synth->cs);
+ LIST_FOR_EACH_ENTRY(preset, &synth->presets, struct preset, entry) + { + if (preset->bank == bank && preset->patch == patch) + { + LeaveCriticalSection(&synth->cs); + return preset->fluid_preset; + } + } + LIST_FOR_EACH_ENTRY(instrument, &synth->instruments, struct instrument, entry) { if (bank == 128 && instrument->patch == (0x80000000 | patch)) break; @@ -1864,18 +1893,35 @@ static fluid_preset_t *synth_sfont_get_preset(fluid_sfont_t *fluid_sfont, int ba
if (&instrument->entry == &synth->instruments) { - fluid_preset = NULL; WARN("Could not find instrument with patch %#x\n", patch); + LeaveCriticalSection(&synth->cs); + return NULL; } - else if ((fluid_preset = new_fluid_preset(fluid_sfont, synth_preset_get_name, synth_preset_get_bank, + + if (!(fluid_preset = new_fluid_preset(fluid_sfont, synth_preset_get_name, synth_preset_get_bank, synth_preset_get_num, synth_preset_noteon, synth_preset_free))) { - fluid_preset_set_data(fluid_preset, instrument); - instrument_addref(instrument); + LeaveCriticalSection(&synth->cs); + return NULL; + }
- TRACE("Created fluid_preset %p for instrument %p\n", fluid_preset, instrument); + if (!(preset = calloc(1, sizeof(struct preset)))) + { + delete_fluid_preset(fluid_preset); + LeaveCriticalSection(&synth->cs); + return NULL; }
+ preset->bank = bank; + preset->patch = patch; + preset->fluid_preset = fluid_preset; + preset->instrument = instrument; + fluid_preset_set_data(fluid_preset, preset); + instrument_addref(instrument); + list_add_tail(&synth->presets, &preset->entry); + + TRACE("Created fluid_preset %p for instrument %p\n", fluid_preset, instrument); + LeaveCriticalSection(&synth->cs);
return fluid_preset; @@ -1925,6 +1971,7 @@ HRESULT synth_create(IUnknown **ret_iface) list_init(&obj->waves); list_init(&obj->events); list_init(&obj->voices); + list_init(&obj->presets);
if (!(obj->fluid_settings = new_fluid_settings())) goto failed; if (!(obj->fluid_sfont = new_fluid_sfont(synth_sfont_get_name, synth_sfont_get_preset,