From: Anton Baskanov baskanov@gmail.com
--- dlls/dmusic/tests/dmusic.c | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)
diff --git a/dlls/dmusic/tests/dmusic.c b/dlls/dmusic/tests/dmusic.c index 3b2f7d9160e..b6fd97c896e 100644 --- a/dlls/dmusic/tests/dmusic.c +++ b/dlls/dmusic/tests/dmusic.c @@ -1035,6 +1035,51 @@ static void test_synthport(void) IDirectMusic_Release(dmusic); }
+static void test_port_kscontrol(void) +{ + IDirectMusicPort *port; + IDirectMusic *dmusic; + IKsControl *control; + KSPROPERTY property; + DWORD volume_size; + LONG volume; + HRESULT hr; + + port = create_synth_port(&dmusic); + hr = IDirectMusicPort_QueryInterface(port, &IID_IKsControl, (void **)&control); + ok(hr == S_OK, "got %#lx\n", hr); + IDirectMusicPort_Release(port); + + property.Set = GUID_DMUS_PROP_Volume; + property.Id = 0; + property.Flags = KSPROPERTY_TYPE_GET; + hr = IKsControl_KsProperty(control, &property, sizeof(property), &volume, sizeof(volume), &volume_size); + todo_wine ok(hr == DMUS_E_GET_UNSUPPORTED, "got hr %#lx.\n", hr); + + property.Set = GUID_DMUS_PROP_Volume; + property.Id = 1; + property.Flags = KSPROPERTY_TYPE_GET; + hr = IKsControl_KsProperty(control, &property, sizeof(property), &volume, sizeof(volume), &volume_size); + todo_wine ok(hr == DMUS_E_UNKNOWN_PROPERTY, "got hr %#lx.\n", hr); + + volume = 0; + property.Set = GUID_DMUS_PROP_Volume; + property.Id = 0; + property.Flags = KSPROPERTY_TYPE_SET; + hr = IKsControl_KsProperty(control, &property, sizeof(property), &volume, sizeof(volume), &volume_size); + todo_wine ok(hr == S_OK, "got hr %#lx.\n", hr); + + volume = 0; + property.Set = GUID_DMUS_PROP_Volume; + property.Id = 1; + property.Flags = KSPROPERTY_TYPE_SET; + hr = IKsControl_KsProperty(control, &property, sizeof(property), &volume, sizeof(volume), &volume_size); + todo_wine ok(hr == DMUS_E_UNKNOWN_PROPERTY, "got hr %#lx.\n", hr); + + IDirectMusicPort_Release(port); + IDirectMusic_Release(dmusic); +} + static void test_port_download(void) { struct wave_download @@ -1665,6 +1710,7 @@ START_TEST(dmusic) test_parsedescriptor(); test_master_clock(); test_synthport(); + test_port_kscontrol(); test_port_download(); test_download_instrument(); test_default_gm_collection();
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmusic/port.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
diff --git a/dlls/dmusic/port.c b/dlls/dmusic/port.c index f98d73f4444..8ce732390e5 100644 --- a/dlls/dmusic/port.c +++ b/dlls/dmusic/port.c @@ -686,6 +686,7 @@ static const IKsControlVtbl ikscontrol_vtbl = { HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_params, DMUS_PORTCAPS *port_caps, IDirectMusicPort **port) { + IKsControl *synth_control; struct synth_port *obj; HRESULT hr = E_FAIL; int i; @@ -711,6 +712,9 @@ HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_param hr = CoCreateInstance(&CLSID_DirectMusicSynth, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynth, (void **)&obj->synth);
+ if (SUCCEEDED(hr)) + hr = IDirectMusicSynth_QueryInterface(obj->synth, &IID_IKsControl, (void **)&synth_control); + if (SUCCEEDED(hr)) hr = CoCreateInstance(&CLSID_DirectMusicSynthSink, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynthSink, (void**)&obj->synth_sink);
@@ -726,6 +730,29 @@ HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_param if (SUCCEEDED(hr)) hr = IDirectMusicSynth_Open(obj->synth, port_params);
+ if (SUCCEEDED(hr)) + { + KSPROPERTY volume_prop; + DWORD volume_size; + LONG volume = 0; + + volume = -600; + volume_prop.Set = GUID_DMUS_PROP_Volume; + volume_prop.Id = 0; + volume_prop.Flags = KSPROPERTY_TYPE_SET; + + IKsControl_KsProperty(synth_control, &volume_prop, sizeof(volume_prop), &volume, + sizeof(volume), &volume_size); + + volume = 0; + volume_prop.Set = GUID_DMUS_PROP_Volume; + volume_prop.Id = 1; + volume_prop.Flags = KSPROPERTY_TYPE_SET; + + IKsControl_KsProperty(synth_control, &volume_prop, sizeof(volume_prop), &volume, + sizeof(volume), &volume_size); + } + if (0) { if (port_params->dwValidParams & DMUS_PORTPARAMS_CHANNELGROUPS) { @@ -753,6 +780,9 @@ HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_param } }
+ if (synth_control) + IKsControl_Release(synth_control); + if (SUCCEEDED(hr)) { *port = &obj->IDirectMusicPort_iface; return S_OK;
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmusic/port.c | 51 ++++++++++++++++++++++++++++++++------ dlls/dmusic/tests/dmusic.c | 8 +++--- 2 files changed, 48 insertions(+), 11 deletions(-)
diff --git a/dlls/dmusic/port.c b/dlls/dmusic/port.c index 8ce732390e5..84a9e759ab2 100644 --- a/dlls/dmusic/port.c +++ b/dlls/dmusic/port.c @@ -42,6 +42,7 @@ struct synth_port { IDirectSound *dsound; IDirectSoundBuffer *dsbuffer; IDirectMusicSynth *synth; + IKsControl *synth_control; IDirectMusicSynthSink *synth_sink; BOOL active; DMUS_PORTPARAMS params; @@ -129,6 +130,7 @@ static ULONG WINAPI synth_port_Release(IDirectMusicPort *iface) IDirectMusicSynthSink_Release(This->synth_sink); IDirectMusicSynth_Activate(This->synth, FALSE); IDirectMusicSynth_Close(This->synth); + IKsControl_Release(This->synth_control); IDirectMusicSynth_Release(This->synth); if (This->dsbuffer) IDirectSoundBuffer_Release(This->dsbuffer); @@ -639,15 +641,52 @@ static ULONG WINAPI IKsControlImpl_Release(IKsControl *iface) static HRESULT WINAPI IKsControlImpl_KsProperty(IKsControl *iface, KSPROPERTY *prop, ULONG prop_len, void *data, ULONG data_len, ULONG *ret_len) { + struct synth_port *This = synth_from_IKsControl(iface); + TRACE("(%p, %p, %lu, %p, %lu, %p)\n", iface, prop, prop_len, data, data_len, ret_len); TRACE("prop = %s - %lu - %lu\n", debugstr_guid(&prop->Set), prop->Id, prop->Flags);
+ if (prop->Flags == KSPROPERTY_TYPE_SET) + { + if (data_len < sizeof(LONG)) + return E_NOT_SUFFICIENT_BUFFER; + + if (IsEqualGUID(&prop->Set, &GUID_DMUS_PROP_Volume)) + { + KSPROPERTY volume_prop; + DWORD volume_size; + + if (prop->Id != 0) + return DMUS_E_UNKNOWN_PROPERTY; + + volume_prop.Set = GUID_DMUS_PROP_Volume; + volume_prop.Id = 1; + volume_prop.Flags = KSPROPERTY_TYPE_SET; + + return IKsControl_KsProperty(This->synth_control, &volume_prop, sizeof(volume_prop), + data, data_len, &volume_size); + } + else + { + FIXME("Unknown property %s\n", debugstr_guid(&prop->Set)); + } + + return S_OK; + } + if (prop->Flags != KSPROPERTY_TYPE_GET) { FIXME("prop flags %lu not yet supported\n", prop->Flags); return S_FALSE; }
+ if (IsEqualGUID(&prop->Set, &GUID_DMUS_PROP_Volume)) + { + if (prop->Id != 0) + return DMUS_E_UNKNOWN_PROPERTY; + return DMUS_E_GET_UNSUPPORTED; + } + if (data_len < sizeof(DWORD)) return E_NOT_SUFFICIENT_BUFFER;
@@ -686,7 +725,6 @@ static const IKsControlVtbl ikscontrol_vtbl = { HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_params, DMUS_PORTCAPS *port_caps, IDirectMusicPort **port) { - IKsControl *synth_control; struct synth_port *obj; HRESULT hr = E_FAIL; int i; @@ -713,7 +751,7 @@ HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_param (void **)&obj->synth);
if (SUCCEEDED(hr)) - hr = IDirectMusicSynth_QueryInterface(obj->synth, &IID_IKsControl, (void **)&synth_control); + hr = IDirectMusicSynth_QueryInterface(obj->synth, &IID_IKsControl, (void **)&obj->synth_control);
if (SUCCEEDED(hr)) hr = CoCreateInstance(&CLSID_DirectMusicSynthSink, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynthSink, (void**)&obj->synth_sink); @@ -741,7 +779,7 @@ HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_param volume_prop.Id = 0; volume_prop.Flags = KSPROPERTY_TYPE_SET;
- IKsControl_KsProperty(synth_control, &volume_prop, sizeof(volume_prop), &volume, + IKsControl_KsProperty(obj->synth_control, &volume_prop, sizeof(volume_prop), &volume, sizeof(volume), &volume_size);
volume = 0; @@ -749,7 +787,7 @@ HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_param volume_prop.Id = 1; volume_prop.Flags = KSPROPERTY_TYPE_SET;
- IKsControl_KsProperty(synth_control, &volume_prop, sizeof(volume_prop), &volume, + IKsControl_KsProperty(obj->synth_control, &volume_prop, sizeof(volume_prop), &volume, sizeof(volume), &volume_size); }
@@ -780,14 +818,13 @@ HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_param } }
- if (synth_control) - IKsControl_Release(synth_control); - if (SUCCEEDED(hr)) { *port = &obj->IDirectMusicPort_iface; return S_OK; }
+ if (obj->synth_control) + IKsControl_Release(obj->synth_control); if (obj->synth) IDirectMusicSynth_Release(obj->synth); if (obj->synth_sink) diff --git a/dlls/dmusic/tests/dmusic.c b/dlls/dmusic/tests/dmusic.c index b6fd97c896e..41041294faa 100644 --- a/dlls/dmusic/tests/dmusic.c +++ b/dlls/dmusic/tests/dmusic.c @@ -1054,27 +1054,27 @@ static void test_port_kscontrol(void) property.Id = 0; property.Flags = KSPROPERTY_TYPE_GET; hr = IKsControl_KsProperty(control, &property, sizeof(property), &volume, sizeof(volume), &volume_size); - todo_wine ok(hr == DMUS_E_GET_UNSUPPORTED, "got hr %#lx.\n", hr); + ok(hr == DMUS_E_GET_UNSUPPORTED, "got hr %#lx.\n", hr);
property.Set = GUID_DMUS_PROP_Volume; property.Id = 1; property.Flags = KSPROPERTY_TYPE_GET; hr = IKsControl_KsProperty(control, &property, sizeof(property), &volume, sizeof(volume), &volume_size); - todo_wine ok(hr == DMUS_E_UNKNOWN_PROPERTY, "got hr %#lx.\n", hr); + ok(hr == DMUS_E_UNKNOWN_PROPERTY, "got hr %#lx.\n", hr);
volume = 0; property.Set = GUID_DMUS_PROP_Volume; property.Id = 0; property.Flags = KSPROPERTY_TYPE_SET; hr = IKsControl_KsProperty(control, &property, sizeof(property), &volume, sizeof(volume), &volume_size); - todo_wine ok(hr == S_OK, "got hr %#lx.\n", hr); + ok(hr == S_OK, "got hr %#lx.\n", hr);
volume = 0; property.Set = GUID_DMUS_PROP_Volume; property.Id = 1; property.Flags = KSPROPERTY_TYPE_SET; hr = IKsControl_KsProperty(control, &property, sizeof(property), &volume, sizeof(volume), &volume_size); - todo_wine ok(hr == DMUS_E_UNKNOWN_PROPERTY, "got hr %#lx.\n", hr); + ok(hr == DMUS_E_UNKNOWN_PROPERTY, "got hr %#lx.\n", hr);
IDirectMusicPort_Release(port); IDirectMusic_Release(dmusic);
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmime/dmime_main.c | 1 + dlls/dmime/performance.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+)
diff --git a/dlls/dmime/dmime_main.c b/dlls/dmime/dmime_main.c index 05d094fc2a2..8fc9cc702f6 100644 --- a/dlls/dmime/dmime_main.c +++ b/dlls/dmime/dmime_main.c @@ -32,6 +32,7 @@ #include "rpcproxy.h" #include "initguid.h" #include "dmusici.h" +#include "dmksctrl.h"
#include "dmime_private.h"
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 3c67fbcadb4..9f35ef1b389 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -20,6 +20,7 @@
#include "dmime_private.h" #include "dmusic_midi.h" +#include "dmksctrl.h" #include "wine/rbtree.h" #include <math.h>
@@ -1141,6 +1142,9 @@ static void performance_update_latency_time(struct performance *This, IDirectMus static HRESULT perf_dmport_create(struct performance *perf, DMUS_PORTPARAMS *params) { IDirectMusicPort *port; + KSPROPERTY volume_prop; + IKsControl *control; + DWORD volume_size; GUID guid; unsigned int i; HRESULT hr; @@ -1151,6 +1155,19 @@ static HRESULT perf_dmport_create(struct performance *perf, DMUS_PORTPARAMS *par if (FAILED(hr = IDirectMusic8_CreatePort(perf->dmusic, &guid, params, &port, NULL))) return hr;
+ if (FAILED(hr = IDirectMusicPort_QueryInterface(port, &IID_IKsControl, (void **)&control))) + { + IDirectMusicPort_Release(port); + return hr; + } + + volume_prop.Set = GUID_DMUS_PROP_Volume; + volume_prop.Id = 0; + volume_prop.Flags = KSPROPERTY_TYPE_SET; + + IKsControl_KsProperty(control, &volume_prop, sizeof(volume_prop), + &perf->lMasterVolume, sizeof(perf->lMasterVolume), &volume_size); + if (FAILED(hr = IDirectMusicPort_SetDirectSound(port, perf->dsound, NULL)) || FAILED(hr = IDirectMusicPort_Activate(port, TRUE))) { @@ -1167,6 +1184,7 @@ static HRESULT perf_dmport_create(struct performance *perf, DMUS_PORTPARAMS *par }
performance_update_latency_time(perf, port, NULL); + IKsControl_Release(control); IDirectMusicPort_Release(port); return S_OK; }
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmime/performance.c | 46 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 9f35ef1b389..45d0511f20e 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -38,6 +38,7 @@ struct channel DWORD midi_group; DWORD midi_channel; IDirectMusicPort *port; + IKsControl *control; };
struct channel_block @@ -269,6 +270,7 @@ static void channel_block_free(struct wine_rb_entry *entry, void *context) for (i = 0; i < ARRAY_SIZE(block->channels); i++) { struct channel *channel = block->channels + i; + if (channel->control) IKsControl_Release(channel->control); if (channel->port) IDirectMusicPort_Release(channel->port); }
@@ -284,7 +286,7 @@ static struct channel *performance_get_channel(struct performance *This, DWORD c }
static HRESULT channel_block_init(struct performance *This, DWORD block_num, - IDirectMusicPort *port, DWORD midi_group) + IDirectMusicPort *port, IKsControl *control, DWORD midi_group) { struct channel_block *block; struct wine_rb_entry *entry; @@ -304,8 +306,10 @@ 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; + if (channel->control) IKsControl_Release(channel->control); if (channel->port) IDirectMusicPort_Release(channel->port); if ((channel->port = port)) IDirectMusicPort_AddRef(channel->port); + if ((channel->control = control)) IKsControl_AddRef(channel->control); }
return S_OK; @@ -1179,7 +1183,7 @@ static HRESULT perf_dmport_create(struct performance *perf, DMUS_PORTPARAMS *par
for (i = 0; i < params->dwChannelGroups; i++) { - if (FAILED(hr = channel_block_init(perf, i, port, i + 1))) + if (FAILED(hr = channel_block_init(perf, i, port, control, i + 1))) ERR("Failed to init channel block, hr %#lx\n", hr); }
@@ -1233,6 +1237,8 @@ static HRESULT WINAPI performance_AssignPChannelBlock(IDirectMusicPerformance8 * DWORD block_num, IDirectMusicPort *port, DWORD midi_group) { struct performance *This = impl_from_IDirectMusicPerformance8(iface); + IKsControl *control; + HRESULT hr;
FIXME("(%p, %ld, %p, %ld): semi-stub\n", This, block_num, port, midi_group);
@@ -1240,7 +1246,10 @@ 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;
- return channel_block_init(This, block_num, port, midi_group); + if (FAILED(hr = IDirectMusicPort_QueryInterface(port, &IID_IKsControl, (void **)&control))) + return hr; + + return channel_block_init(This, block_num, port, control, midi_group); }
static HRESULT WINAPI performance_AssignPChannel(IDirectMusicPerformance8 *iface, DWORD channel_num, @@ -1248,6 +1257,7 @@ static HRESULT WINAPI performance_AssignPChannel(IDirectMusicPerformance8 *iface { struct performance *This = impl_from_IDirectMusicPerformance8(iface); struct channel *channel; + IKsControl *control; HRESULT hr;
FIXME("(%p)->(%ld, %p, %ld, %ld) semi-stub\n", This, channel_num, port, midi_group, midi_channel); @@ -1255,6 +1265,9 @@ static HRESULT WINAPI performance_AssignPChannel(IDirectMusicPerformance8 *iface if (!port) return E_POINTER; if (This->audio_paths_enabled) return DMUS_E_AUDIOPATHS_IN_USE;
+ if (FAILED(hr = IDirectMusicPort_QueryInterface(port, &IID_IKsControl, (void **)&control))) + return hr; + if (!(channel = performance_get_channel(This, channel_num))) { if (FAILED(hr = IDirectMusicPerformance8_AssignPChannelBlock(iface, @@ -1266,8 +1279,12 @@ static HRESULT WINAPI performance_AssignPChannel(IDirectMusicPerformance8 *iface
channel->midi_group = midi_group; channel->midi_channel = midi_channel; + if (channel->control) IDirectMusicPort_Release(channel->control); if (channel->port) IDirectMusicPort_Release(channel->port); if ((channel->port = port)) IDirectMusicPort_AddRef(channel->port); + if ((channel->control = control)) IKsControl_AddRef(channel->control); + + IKsControl_Release(control);
return S_OK; } @@ -1371,6 +1388,28 @@ static HRESULT WINAPI performance_GetGlobalParam(IDirectMusicPerformance8 *iface return S_OK; }
+static void update_master_volume(struct performance *This) +{ + struct channel_block *block; + KSPROPERTY volume_prop; + DWORD volume_size; + int i; + + volume_prop.Set = GUID_DMUS_PROP_Volume; + volume_prop.Id = 0; + volume_prop.Flags = KSPROPERTY_TYPE_SET; + + RB_FOR_EACH_ENTRY(block, &This->channel_blocks, struct channel_block, entry) + { + for (i = 0; i < ARRAYSIZE(block->channels); ++i) + { + IKsControl_KsProperty(block->channels[i].control, &volume_prop, + sizeof(volume_prop), &This->lMasterVolume, sizeof(This->lMasterVolume), + &volume_size); + } + } +} + static HRESULT WINAPI performance_SetGlobalParam(IDirectMusicPerformance8 *iface, REFGUID rguidType, void *pParam, DWORD dwSize) { @@ -1392,6 +1431,7 @@ static HRESULT WINAPI performance_SetGlobalParam(IDirectMusicPerformance8 *iface } if (IsEqualGUID (rguidType, &GUID_PerfMasterVolume)) { memcpy(&This->lMasterVolume, pParam, dwSize); + update_master_volume(This); TRACE("=> MasterVolume set to %li\n", This->lMasterVolume); }