From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/performance.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 94d7d8aeea3..3f40ecd5549 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -32,7 +32,8 @@ enum dmus_internal_message_type DMUS_PMSGT_INTERNAL_SEGMENT_TICK, };
-struct pchannel_block { +struct channel_block +{ DWORD block_num; /* Block 0 is PChannels 0-15, Block 1 is PChannels 16-31, etc */ struct { DWORD channel; /* MIDI channel */ @@ -56,7 +57,7 @@ struct performance float fMasterTempo; long lMasterVolume; /* performance channels */ - struct wine_rb_tree pchannels; + struct wine_rb_tree channel_blocks;
BOOL audio_paths_enabled; IDirectMusicAudioPath *pDefaultPath; @@ -233,30 +234,28 @@ static HRESULT performance_send_notification_pmsg(struct performance *This, MUSI return hr; }
-static int pchannel_block_compare(const void *key, const struct wine_rb_entry *entry) +static int channel_block_compare(const void *key, const struct wine_rb_entry *entry) { - const struct pchannel_block *b = WINE_RB_ENTRY_VALUE(entry, const struct pchannel_block, entry); - + const struct channel_block *b = WINE_RB_ENTRY_VALUE(entry, const struct channel_block, entry); return *(DWORD *)key - b->block_num; }
-static void pchannel_block_free(struct wine_rb_entry *entry, void *context) +static void channel_block_free(struct wine_rb_entry *entry, void *context) { - struct pchannel_block *b = WINE_RB_ENTRY_VALUE(entry, struct pchannel_block, entry); - + struct channel_block *b = WINE_RB_ENTRY_VALUE(entry, struct channel_block, entry); free(b); }
-static struct pchannel_block *pchannel_block_set(struct wine_rb_tree *tree, DWORD block_num, +static struct channel_block *channel_block_set(struct wine_rb_tree *tree, DWORD block_num, IDirectMusicPort *port, DWORD group, BOOL only_set_new) { - struct pchannel_block *block; + struct channel_block *block; struct wine_rb_entry *entry; unsigned int i;
entry = wine_rb_get(tree, &block_num); if (entry) { - block = WINE_RB_ENTRY_VALUE(entry, struct pchannel_block, entry); + block = WINE_RB_ENTRY_VALUE(entry, struct channel_block, entry); if (only_set_new) return block; } else { @@ -408,7 +407,7 @@ static ULONG WINAPI performance_Release(IDirectMusicPerformance8 *iface) TRACE("(%p): ref=%ld\n", This, ref);
if (ref == 0) { - wine_rb_destroy(&This->pchannels, pchannel_block_free, NULL); + wine_rb_destroy(&This->channel_blocks, channel_block_free, NULL); This->safe.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->safe); free(This); @@ -984,7 +983,7 @@ static HRESULT perf_dmport_create(struct performance *perf, DMUS_PORTPARAMS *par }
for (i = 0; i < params->dwChannelGroups; i++) - pchannel_block_set(&perf->pchannels, i, port, i + 1, FALSE); + channel_block_set(&perf->channel_blocks, i, port, i + 1, FALSE);
performance_update_latency_time(perf, port, NULL); return S_OK; @@ -1041,7 +1040,7 @@ static HRESULT WINAPI performance_AssignPChannelBlock(IDirectMusicPerformance8 * if (block_num > MAXDWORD / 16) return E_INVALIDARG; if (This->audio_paths_enabled) return DMUS_E_AUDIOPATHS_IN_USE;
- pchannel_block_set(&This->pchannels, block_num, port, group, FALSE); + channel_block_set(&This->channel_blocks, block_num, port, group, FALSE);
return S_OK; } @@ -1050,14 +1049,14 @@ static HRESULT WINAPI performance_AssignPChannel(IDirectMusicPerformance8 *iface IDirectMusicPort *port, DWORD group, DWORD channel) { struct performance *This = impl_from_IDirectMusicPerformance8(iface); - struct pchannel_block *block; + struct channel_block *block;
FIXME("(%p)->(%ld, %p, %ld, %ld) semi-stub\n", This, pchannel, port, group, channel);
if (!port) return E_POINTER; if (This->audio_paths_enabled) return DMUS_E_AUDIOPATHS_IN_USE;
- block = pchannel_block_set(&This->pchannels, pchannel / 16, port, 0, TRUE); + block = channel_block_set(&This->channel_blocks, pchannel / 16, port, 0, TRUE); if (block) { block->pchannel[pchannel % 16].group = group; block->pchannel[pchannel % 16].channel = channel; @@ -1070,17 +1069,17 @@ static HRESULT WINAPI performance_PChannelInfo(IDirectMusicPerformance8 *iface, IDirectMusicPort **port, DWORD *group, DWORD *channel) { struct performance *This = impl_from_IDirectMusicPerformance8(iface); - struct pchannel_block *block; + struct channel_block *block; struct wine_rb_entry *entry; DWORD block_num = pchannel / 16; unsigned int index = pchannel % 16;
TRACE("(%p)->(%ld, %p, %p, %p)\n", This, pchannel, port, group, channel);
- entry = wine_rb_get(&This->pchannels, &block_num); + entry = wine_rb_get(&This->channel_blocks, &block_num); if (!entry) return E_INVALIDARG; - block = WINE_RB_ENTRY_VALUE(entry, struct pchannel_block, entry); + block = WINE_RB_ENTRY_VALUE(entry, struct channel_block, entry);
if (port) { *port = block->pchannel[index].port; @@ -2080,7 +2079,7 @@ HRESULT create_dmperformance(REFIID iid, void **ret_iface) obj->pDefaultPath = NULL; InitializeCriticalSection(&obj->safe); obj->safe.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": performance->safe"); - wine_rb_init(&obj->pchannels, pchannel_block_compare); + wine_rb_init(&obj->channel_blocks, channel_block_compare);
list_init(&obj->messages); list_init(&obj->notifications);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/performance.c | 57 ++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 28 deletions(-)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 3f40ecd5549..b46e5ae8609 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -32,14 +32,17 @@ enum dmus_internal_message_type DMUS_PMSGT_INTERNAL_SEGMENT_TICK, };
+struct channel +{ + DWORD midi_group; + DWORD midi_channel; + IDirectMusicPort *port; +}; + struct channel_block { DWORD block_num; /* Block 0 is PChannels 0-15, Block 1 is PChannels 16-31, etc */ - struct { - DWORD channel; /* MIDI channel */ - DWORD group; /* MIDI group */ - IDirectMusicPort *port; - } pchannel[16]; + struct channel channels[16]; struct wine_rb_entry entry; };
@@ -247,7 +250,7 @@ static void channel_block_free(struct wine_rb_entry *entry, void *context) }
static struct channel_block *channel_block_set(struct wine_rb_tree *tree, DWORD block_num, - IDirectMusicPort *port, DWORD group, BOOL only_set_new) + IDirectMusicPort *port, DWORD midi_group, BOOL only_set_new) { struct channel_block *block; struct wine_rb_entry *entry; @@ -264,9 +267,9 @@ static struct channel_block *channel_block_set(struct wine_rb_tree *tree, DWORD }
for (i = 0; i < 16; ++i) { - block->pchannel[i].port = port; - block->pchannel[i].group = group; - block->pchannel[i].channel = i; + block->channels[i].port = port; + block->channels[i].midi_group = midi_group; + block->channels[i].midi_channel = i; } if (!entry) wine_rb_put(tree, &block->block_num, &block->entry); @@ -1030,51 +1033,51 @@ static HRESULT WINAPI performance_RemovePort(IDirectMusicPerformance8 *iface, ID }
static HRESULT WINAPI performance_AssignPChannelBlock(IDirectMusicPerformance8 *iface, - DWORD block_num, IDirectMusicPort *port, DWORD group) + DWORD block_num, IDirectMusicPort *port, DWORD midi_group) { struct performance *This = impl_from_IDirectMusicPerformance8(iface);
- FIXME("(%p, %ld, %p, %ld): semi-stub\n", This, block_num, port, group); + FIXME("(%p, %ld, %p, %ld): semi-stub\n", This, block_num, port, midi_group);
if (!port) return E_POINTER; if (block_num > MAXDWORD / 16) return E_INVALIDARG; if (This->audio_paths_enabled) return DMUS_E_AUDIOPATHS_IN_USE;
- channel_block_set(&This->channel_blocks, block_num, port, group, FALSE); + channel_block_set(&This->channel_blocks, block_num, port, midi_group, FALSE);
return S_OK; }
-static HRESULT WINAPI performance_AssignPChannel(IDirectMusicPerformance8 *iface, DWORD pchannel, - IDirectMusicPort *port, DWORD group, DWORD channel) +static HRESULT WINAPI performance_AssignPChannel(IDirectMusicPerformance8 *iface, DWORD channel_num, + IDirectMusicPort *port, DWORD midi_group, DWORD midi_channel) { struct performance *This = impl_from_IDirectMusicPerformance8(iface); struct channel_block *block;
- FIXME("(%p)->(%ld, %p, %ld, %ld) semi-stub\n", This, pchannel, port, group, channel); + FIXME("(%p)->(%ld, %p, %ld, %ld) semi-stub\n", This, channel_num, port, midi_group, midi_channel);
if (!port) return E_POINTER; if (This->audio_paths_enabled) return DMUS_E_AUDIOPATHS_IN_USE;
- block = channel_block_set(&This->channel_blocks, pchannel / 16, port, 0, TRUE); + block = channel_block_set(&This->channel_blocks, channel_num / 16, port, 0, TRUE); if (block) { - block->pchannel[pchannel % 16].group = group; - block->pchannel[pchannel % 16].channel = channel; + block->channels[channel_num % 16].midi_group = midi_group; + block->channels[channel_num % 16].midi_channel = midi_channel; }
return S_OK; }
-static HRESULT WINAPI performance_PChannelInfo(IDirectMusicPerformance8 *iface, DWORD pchannel, - IDirectMusicPort **port, DWORD *group, DWORD *channel) +static HRESULT WINAPI performance_PChannelInfo(IDirectMusicPerformance8 *iface, DWORD channel_num, + IDirectMusicPort **port, DWORD *midi_group, DWORD *midi_channel) { struct performance *This = impl_from_IDirectMusicPerformance8(iface); struct channel_block *block; struct wine_rb_entry *entry; - DWORD block_num = pchannel / 16; - unsigned int index = pchannel % 16; + DWORD block_num = channel_num / 16; + unsigned int index = channel_num % 16;
- TRACE("(%p)->(%ld, %p, %p, %p)\n", This, pchannel, port, group, channel); + TRACE("(%p)->(%ld, %p, %p, %p)\n", This, channel_num, port, midi_group, midi_channel);
entry = wine_rb_get(&This->channel_blocks, &block_num); if (!entry) @@ -1082,13 +1085,11 @@ static HRESULT WINAPI performance_PChannelInfo(IDirectMusicPerformance8 *iface, block = WINE_RB_ENTRY_VALUE(entry, struct channel_block, entry);
if (port) { - *port = block->pchannel[index].port; + *port = block->channels[index].port; IDirectMusicPort_AddRef(*port); } - if (group) - *group = block->pchannel[index].group; - if (channel) - *channel = block->pchannel[index].channel; + if (midi_group) *midi_group = block->channels[index].midi_group; + if (midi_channel) *midi_channel = block->channels[index].midi_channel;
return S_OK; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/performance.c | 46 ++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 18 deletions(-)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index b46e5ae8609..7269cd07670 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -249,6 +249,14 @@ static void channel_block_free(struct wine_rb_entry *entry, void *context) free(b); }
+static struct channel *performance_get_channel(struct performance *This, DWORD channel_num) +{ + DWORD block_num = channel_num / 16; + struct wine_rb_entry *entry; + if (!(entry = wine_rb_get(&This->channel_blocks, &block_num))) return NULL; + return WINE_RB_ENTRY_VALUE(entry, struct channel_block, entry)->channels + channel_num % 16; +} + static struct channel_block *channel_block_set(struct wine_rb_tree *tree, DWORD block_num, IDirectMusicPort *port, DWORD midi_group, BOOL only_set_new) { @@ -1052,19 +1060,27 @@ static HRESULT WINAPI performance_AssignPChannel(IDirectMusicPerformance8 *iface IDirectMusicPort *port, DWORD midi_group, DWORD midi_channel) { struct performance *This = impl_from_IDirectMusicPerformance8(iface); - struct channel_block *block; + struct channel *channel; + HRESULT hr;
FIXME("(%p)->(%ld, %p, %ld, %ld) semi-stub\n", This, channel_num, port, midi_group, midi_channel);
if (!port) return E_POINTER; if (This->audio_paths_enabled) return DMUS_E_AUDIOPATHS_IN_USE;
- block = channel_block_set(&This->channel_blocks, channel_num / 16, port, 0, TRUE); - if (block) { - block->channels[channel_num % 16].midi_group = midi_group; - block->channels[channel_num % 16].midi_channel = midi_channel; + if (!(channel = performance_get_channel(This, channel_num))) + { + if (FAILED(hr = IDirectMusicPerformance8_AssignPChannelBlock(iface, + channel_num / 16, port, 0))) + return hr; + if (!(channel = performance_get_channel(This, channel_num))) + return DMUS_E_NOT_FOUND; }
+ channel->midi_group = midi_group; + channel->midi_channel = midi_channel; + channel->port = port; + return S_OK; }
@@ -1072,24 +1088,18 @@ static HRESULT WINAPI performance_PChannelInfo(IDirectMusicPerformance8 *iface, IDirectMusicPort **port, DWORD *midi_group, DWORD *midi_channel) { struct performance *This = impl_from_IDirectMusicPerformance8(iface); - struct channel_block *block; - struct wine_rb_entry *entry; - DWORD block_num = channel_num / 16; - unsigned int index = channel_num % 16; + struct channel *channel;
TRACE("(%p)->(%ld, %p, %p, %p)\n", This, channel_num, port, midi_group, midi_channel);
- entry = wine_rb_get(&This->channel_blocks, &block_num); - if (!entry) - return E_INVALIDARG; - block = WINE_RB_ENTRY_VALUE(entry, struct channel_block, entry); - - if (port) { - *port = block->channels[index].port; + if (!(channel = performance_get_channel(This, channel_num))) return E_INVALIDARG; + if (port) + { + *port = channel->port; IDirectMusicPort_AddRef(*port); } - if (midi_group) *midi_group = block->channels[index].midi_group; - if (midi_channel) *midi_channel = block->channels[index].midi_channel; + if (midi_group) *midi_group = channel->midi_group; + if (midi_channel) *midi_channel = channel->midi_channel;
return S_OK; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/performance.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 7269cd07670..4b169427371 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -257,32 +257,31 @@ static struct channel *performance_get_channel(struct performance *This, DWORD c return WINE_RB_ENTRY_VALUE(entry, struct channel_block, entry)->channels + channel_num % 16; }
-static struct channel_block *channel_block_set(struct wine_rb_tree *tree, DWORD block_num, - IDirectMusicPort *port, DWORD midi_group, BOOL only_set_new) +static HRESULT channel_block_init(struct performance *This, DWORD block_num, + IDirectMusicPort *port, DWORD midi_group) { struct channel_block *block; struct wine_rb_entry *entry; - unsigned int i; + UINT i;
- entry = wine_rb_get(tree, &block_num); - if (entry) { + if ((entry = wine_rb_get(&This->channel_blocks, &block_num))) block = WINE_RB_ENTRY_VALUE(entry, struct channel_block, entry); - if (only_set_new) - return block; - } else { - if (!(block = malloc(sizeof(*block)))) return NULL; + else + { + if (!(block = calloc(1, sizeof(*block)))) return E_OUTOFMEMORY; block->block_num = block_num; + wine_rb_put(&This->channel_blocks, &block_num, &block->entry); }
- for (i = 0; i < 16; ++i) { - block->channels[i].port = port; - block->channels[i].midi_group = midi_group; - block->channels[i].midi_channel = i; + for (i = 0; i < ARRAY_SIZE(block->channels); ++i) + { + struct channel *channel = block->channels + i; + channel->midi_group = midi_group; + channel->midi_channel = i; + channel->port = port; } - if (!entry) - wine_rb_put(tree, &block->block_num, &block->entry);
- return block; + return S_OK; }
static inline struct performance *impl_from_IDirectMusicPerformance8(IDirectMusicPerformance8 *iface) @@ -994,7 +993,10 @@ static HRESULT perf_dmport_create(struct performance *perf, DMUS_PORTPARAMS *par }
for (i = 0; i < params->dwChannelGroups; i++) - channel_block_set(&perf->channel_blocks, i, port, i + 1, FALSE); + { + if (FAILED(hr = channel_block_init(perf, i, port, i + 1))) + ERR("Failed to init channel block, hr %#lx\n", hr); + }
performance_update_latency_time(perf, port, NULL); return S_OK; @@ -1051,9 +1053,7 @@ static HRESULT WINAPI performance_AssignPChannelBlock(IDirectMusicPerformance8 * if (block_num > MAXDWORD / 16) return E_INVALIDARG; if (This->audio_paths_enabled) return DMUS_E_AUDIOPATHS_IN_USE;
- channel_block_set(&This->channel_blocks, block_num, port, midi_group, FALSE); - - return S_OK; + return channel_block_init(This, block_num, port, midi_group); }
static HRESULT WINAPI performance_AssignPChannel(IDirectMusicPerformance8 *iface, DWORD channel_num,
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/performance.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 4b169427371..0e817d232e3 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -245,8 +245,16 @@ static int channel_block_compare(const void *key, const struct wine_rb_entry *en
static void channel_block_free(struct wine_rb_entry *entry, void *context) { - struct channel_block *b = WINE_RB_ENTRY_VALUE(entry, struct channel_block, entry); - free(b); + struct channel_block *block = WINE_RB_ENTRY_VALUE(entry, struct channel_block, entry); + UINT i; + + for (i = 0; i < ARRAY_SIZE(block->channels); i++) + { + struct channel *channel = block->channels + i; + if (channel->port) IDirectMusicPort_Release(channel->port); + } + + free(block); }
static struct channel *performance_get_channel(struct performance *This, DWORD channel_num) @@ -278,7 +286,8 @@ static HRESULT channel_block_init(struct performance *This, DWORD block_num, struct channel *channel = block->channels + i; channel->midi_group = midi_group; channel->midi_channel = i; - channel->port = port; + if (channel->port) IDirectMusicPort_Release(channel->port); + if ((channel->port = port)) IDirectMusicPort_AddRef(channel->port); }
return S_OK; @@ -992,6 +1001,8 @@ static HRESULT perf_dmport_create(struct performance *perf, DMUS_PORTPARAMS *par return hr; }
+ wine_rb_destroy(&perf->channel_blocks, channel_block_free, NULL); + for (i = 0; i < params->dwChannelGroups; i++) { if (FAILED(hr = channel_block_init(perf, i, port, i + 1))) @@ -999,6 +1010,7 @@ static HRESULT perf_dmport_create(struct performance *perf, DMUS_PORTPARAMS *par }
performance_update_latency_time(perf, port, NULL); + IDirectMusicPort_Release(port); return S_OK; }
@@ -1079,7 +1091,8 @@ static HRESULT WINAPI performance_AssignPChannel(IDirectMusicPerformance8 *iface
channel->midi_group = midi_group; channel->midi_channel = midi_channel; - channel->port = port; + if (channel->port) IDirectMusicPort_Release(channel->port); + if ((channel->port = port)) IDirectMusicPort_AddRef(channel->port);
return S_OK; }
The leak causes some game to spawn hundred of synth threads as they call CreateStandardAudioPath dozen of times.
This merge request was approved by Michael Stefaniuc.
Unrelated test failures in device.c and win.c