From: Yuxuan Shui yshui@codeweavers.com
AudioPaths are created from IDirectMusicPerformance::CreateAudioPath and CreateStandardAudioPath, and don't have an IDirectMusicObject or an IPersistStream interface. On the other hand AudioPathConfigs are loaded from files, and do have IDirectMusicObject and IPersistStream.
They were somehow confused with each other and implemented in the same struct, this commit fixes that. --- dlls/dmime/audiopath.c | 92 +++++++++++++++++++++++++++++++++----- dlls/dmime/dmime_main.c | 4 +- dlls/dmime/dmime_private.h | 1 + dlls/dmime/tests/dmime.c | 12 +++-- 4 files changed, 88 insertions(+), 21 deletions(-)
diff --git a/dlls/dmime/audiopath.c b/dlls/dmime/audiopath.c index 65691f4705f..90843f7a941 100644 --- a/dlls/dmime/audiopath.c +++ b/dlls/dmime/audiopath.c @@ -23,7 +23,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(dmime);
struct IDirectMusicAudioPathImpl { IDirectMusicAudioPath IDirectMusicAudioPath_iface; - struct dmobject dmobj; LONG ref; IDirectMusicPerformance8* pPerf; IDirectMusicGraph* pToolGraph; @@ -33,14 +32,20 @@ struct IDirectMusicAudioPathImpl { BOOL fActive; };
+struct audio_path_config { + IUnknown unk; + struct dmobject dmobj; + LONG ref; +}; + static inline struct IDirectMusicAudioPathImpl *impl_from_IDirectMusicAudioPath(IDirectMusicAudioPath *iface) { return CONTAINING_RECORD(iface, struct IDirectMusicAudioPathImpl, IDirectMusicAudioPath_iface); }
-static inline struct IDirectMusicAudioPathImpl *impl_from_IPersistStream(IPersistStream *iface) +static inline struct audio_path_config *impl_from_IPersistStream(IPersistStream *iface) { - return CONTAINING_RECORD(iface, struct IDirectMusicAudioPathImpl, dmobj.IPersistStream_iface); + return CONTAINING_RECORD(iface, struct audio_path_config, dmobj.IPersistStream_iface); }
void set_audiopath_perf_pointer(IDirectMusicAudioPath *iface, IDirectMusicPerformance8 *performance) @@ -74,10 +79,6 @@ static HRESULT WINAPI IDirectMusicAudioPathImpl_QueryInterface (IDirectMusicAudi
if (IsEqualIID (riid, &IID_IDirectMusicAudioPath) || IsEqualIID (riid, &IID_IUnknown)) *ppobj = &This->IDirectMusicAudioPath_iface; - else if (IsEqualIID (riid, &IID_IDirectMusicObject)) - *ppobj = &This->dmobj.IDirectMusicObject_iface; - else if (IsEqualIID (riid, &IID_IPersistStream)) - *ppobj = &This->dmobj.IPersistStream_iface;
if (*ppobj) { IUnknown_AddRef((IUnknown*)*ppobj); @@ -300,7 +301,7 @@ static const IDirectMusicObjectVtbl dmobject_vtbl = { /* IPersistStream */ static HRESULT WINAPI path_IPersistStream_Load(IPersistStream *iface, IStream *stream) { - struct IDirectMusicAudioPathImpl *This = impl_from_IPersistStream(iface); + struct audio_path_config *This = impl_from_IPersistStream(iface);
FIXME("(%p, %p): Loading not implemented yet\n", This, stream);
@@ -319,6 +320,57 @@ static const IPersistStreamVtbl persiststream_vtbl = { unimpl_IPersistStream_GetSizeMax };
+static struct audio_path_config *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, struct audio_path_config, unk); +} + +static HRESULT WINAPI path_config_IUnknown_QueryInterface(IUnknown *unk, REFIID riid, void **ppobj) +{ + struct audio_path_config *This = impl_from_IUnknown(unk); + + TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj); + + *ppobj = NULL; + + if (IsEqualIID (riid, &IID_IUnknown)) + *ppobj = &This->unk; + else if (IsEqualIID (riid, &IID_IDirectMusicObject)) + *ppobj = &This->dmobj.IDirectMusicObject_iface; + else if (IsEqualIID (riid, &IID_IPersistStream)) + *ppobj = &This->dmobj.IPersistStream_iface; + + if (*ppobj) { + IUnknown_AddRef((IUnknown*)*ppobj); + return S_OK; + } + + WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj); + return E_NOINTERFACE; +} + +static ULONG WINAPI path_config_IUnknown_AddRef(IUnknown *unk) +{ + struct audio_path_config *This = impl_from_IUnknown(unk); + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI path_config_IUnknown_Release(IUnknown *unk) +{ + struct audio_path_config *This = impl_from_IUnknown(unk); + ULONG ref = InterlockedDecrement(&This->ref); + + if (!ref) + free(This); + return ref; +} + +static const IUnknownVtbl path_config_unk_vtbl = { + path_config_IUnknown_QueryInterface, + path_config_IUnknown_AddRef, + path_config_IUnknown_Release, +}; + /* for ClassFactory */ HRESULT create_dmaudiopath(REFIID riid, void **ppobj) { @@ -329,12 +381,28 @@ HRESULT create_dmaudiopath(REFIID riid, void **ppobj) if (!(obj = calloc(1, sizeof(*obj)))) return E_OUTOFMEMORY; obj->IDirectMusicAudioPath_iface.lpVtbl = &DirectMusicAudioPathVtbl; obj->ref = 1; - dmobject_init(&obj->dmobj, &CLSID_DirectMusicAudioPathConfig, - (IUnknown *)&obj->IDirectMusicAudioPath_iface); - obj->dmobj.IDirectMusicObject_iface.lpVtbl = &dmobject_vtbl; - obj->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl;
hr = IDirectMusicAudioPath_QueryInterface(&obj->IDirectMusicAudioPath_iface, riid, ppobj); IDirectMusicAudioPath_Release(&obj->IDirectMusicAudioPath_iface); return hr; } + +HRESULT create_dmaudiopath_config(REFIID riid, void **ppobj) +{ + struct audio_path_config *obj; + HRESULT hr; + + *ppobj = NULL; + obj = calloc(1, sizeof(*obj)); + if (!obj) + return E_OUTOFMEMORY; + dmobject_init(&obj->dmobj, &CLSID_DirectMusicAudioPathConfig, &obj->unk); + obj->unk.lpVtbl = &path_config_unk_vtbl; + obj->dmobj.IDirectMusicObject_iface.lpVtbl = &dmobject_vtbl; + obj->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl; + obj->ref = 1; + + hr = IUnknown_QueryInterface(&obj->unk, riid, ppobj); + IUnknown_Release(&obj->unk); + return hr; +} diff --git a/dlls/dmime/dmime_main.c b/dlls/dmime/dmime_main.c index 89e70bcd1bd..05d094fc2a2 100644 --- a/dlls/dmime/dmime_main.c +++ b/dlls/dmime/dmime_main.c @@ -120,7 +120,7 @@ static IClassFactoryImpl ParamControlTrack_CF = {{&classfactory_vtbl}, create_dm static IClassFactoryImpl MarkerTrack_CF = {{&classfactory_vtbl}, create_dmmarkertrack}; static IClassFactoryImpl LyricsTrack_CF = {{&classfactory_vtbl}, create_dmlyricstrack}; static IClassFactoryImpl SegTriggerTrack_CF = {{&classfactory_vtbl}, create_dmsegtriggertrack}; -static IClassFactoryImpl AudioPath_CF = {{&classfactory_vtbl}, create_dmaudiopath}; +static IClassFactoryImpl AudioPathConfig_CF = {{&classfactory_vtbl}, create_dmaudiopath_config}; static IClassFactoryImpl WaveTrack_CF = {{&classfactory_vtbl}, create_dmwavetrack};
@@ -182,7 +182,7 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) return S_OK; } else if (IsEqualCLSID (rclsid, &CLSID_DirectMusicAudioPathConfig) && IsEqualIID (riid, &IID_IClassFactory)) { - *ppv = &AudioPath_CF; + *ppv = &AudioPathConfig_CF; IClassFactory_AddRef((IClassFactory*)*ppv); return S_OK; } else if (IsEqualCLSID (rclsid, &CLSID_DirectMusicWaveTrack) && IsEqualIID (riid, &IID_IClassFactory)) { diff --git a/dlls/dmime/dmime_private.h b/dlls/dmime/dmime_private.h index ed1589ece1a..7b744419c38 100644 --- a/dlls/dmime/dmime_private.h +++ b/dlls/dmime/dmime_private.h @@ -57,6 +57,7 @@ extern HRESULT create_dmsegment(REFIID riid, void **ret_iface); extern HRESULT create_dmsegmentstate(REFIID riid, void **ret_iface); extern HRESULT create_dmgraph(REFIID riid, void **ret_iface); extern HRESULT create_dmaudiopath(REFIID riid, void **ret_iface); +extern HRESULT create_dmaudiopath_config(REFIID riid, void **ret_iface);
extern HRESULT create_dmlyricstrack(REFIID riid, void **ret_iface); extern HRESULT create_dmmarkertrack(REFIID riid, void **ret_iface); diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index f5ae845cf97..2b7c744acdb 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -908,12 +908,10 @@ static void test_COM_audiopath(void)
/* IDirectMusicObject and IPersistStream are not supported */ hr = IDirectMusicAudioPath_QueryInterface(dmap, &IID_IDirectMusicObject, (void**)&unk); - todo_wine ok(FAILED(hr) && !unk, "Unexpected IDirectMusicObject interface: hr=%#lx, iface=%p\n", - hr, unk); + ok(FAILED(hr) && !unk, "Unexpected IDirectMusicObject interface: hr=%#lx, iface=%p\n", hr, unk); if (unk) IUnknown_Release(unk); hr = IDirectMusicAudioPath_QueryInterface(dmap, &IID_IPersistStream, (void**)&unk); - todo_wine ok(FAILED(hr) && !unk, "Unexpected IPersistStream interface: hr=%#lx, iface=%p\n", - hr, unk); + ok(FAILED(hr) && !unk, "Unexpected IPersistStream interface: hr=%#lx, iface=%p\n", hr, unk); if (unk) IUnknown_Release(unk);
/* Same refcount for all DirectMusicAudioPath interfaces */ @@ -988,7 +986,7 @@ static void test_COM_audiopathconfig(void) /* IDirectMusicAudioPath not supported */ hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicAudioPath, (void**)&dmap); - todo_wine ok(FAILED(hr) && !dmap, + ok(FAILED(hr) && !dmap, "Unexpected IDirectMusicAudioPath interface: hr=%#lx, iface=%p\n", hr, dmap);
/* IDirectMusicObject and IPersistStream supported */ @@ -1018,8 +1016,8 @@ static void test_COM_audiopathconfig(void)
/* IDirectMusicAudioPath still not supported */ hr = IDirectMusicObject_QueryInterface(dmo, &IID_IDirectMusicAudioPath, (void**)&dmap); - todo_wine ok(FAILED(hr) && !dmap, - "Unexpected IDirectMusicAudioPath interface: hr=%#lx, iface=%p\n", hr, dmap); + ok(FAILED(hr) && !dmap, + "Unexpected IDirectMusicAudioPath interface: hr=%#lx, iface=%p\n", hr, dmap);
while (IDirectMusicObject_Release(dmo)); }
From: Yuxuan Shui yshui@codeweavers.com
--- dlls/dmime/audiopath.c | 274 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 269 insertions(+), 5 deletions(-)
diff --git a/dlls/dmime/audiopath.c b/dlls/dmime/audiopath.c index 90843f7a941..70985a261f8 100644 --- a/dlls/dmime/audiopath.c +++ b/dlls/dmime/audiopath.c @@ -32,10 +32,28 @@ struct IDirectMusicAudioPathImpl { BOOL fActive; };
+struct audio_path_pchannel_to_buffer { + struct list entry; + DMUS_IO_PCHANNELTOBUFFER_HEADER header; + + ULONG num_of_guids; + GUID *guids; +}; + +struct audio_path_port_config { + struct list entry; + DMUS_IO_PORTCONFIG_HEADER header; + DMUS_PORTPARAMS8 params; + + struct list pchannel_to_buffer_entries; +}; + struct audio_path_config { IUnknown unk; struct dmobject dmobj; LONG ref; + + struct list port_config_entries; };
static inline struct IDirectMusicAudioPathImpl *impl_from_IDirectMusicAudioPath(IDirectMusicAudioPath *iface) @@ -297,16 +315,240 @@ static const IDirectMusicObjectVtbl dmobject_vtbl = { dmobj_IDirectMusicObject_SetDescriptor, path_IDirectMusicObject_ParseDescriptor }; +static HRESULT parse_pchannel_to_buffers_list(struct audio_path_port_config *This, IStream *stream, const struct chunk_entry *pchl) +{ + struct chunk_entry chunk = { .parent = pchl }; + struct audio_path_pchannel_to_buffer *pchannel_to_buffer = NULL; + ULONG bytes, i; + HRESULT hr; + + while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) { + switch (chunk.id) + { + case DMUS_FOURCC_PCHANNELS_ITEM: + pchannel_to_buffer = calloc(1, sizeof(*pchannel_to_buffer)); + if (!pchannel_to_buffer) + return E_OUTOFMEMORY; + + hr = stream_read(stream, &pchannel_to_buffer->header, sizeof(pchannel_to_buffer->header)); + if (FAILED(hr)) + goto done; + + TRACE("Got PChannelToBuffer header:\n"); + TRACE("\tdwPChannelCount: %lu\n", pchannel_to_buffer->header.dwPChannelCount); + TRACE("\tdwPChannelBase: %lu\n", pchannel_to_buffer->header.dwPChannelBase); + TRACE("\tdwBufferCount: %lu\n", pchannel_to_buffer->header.dwBufferCount); + TRACE("\tdwFlags: %lx\n", pchannel_to_buffer->header.dwFlags); + + bytes = chunk.size - sizeof(pchannel_to_buffer->header); + + if (bytes % sizeof(GUID)) + { + WARN("Invalid size of GUIDs array\n"); + hr = E_FAIL; + goto done; + } + pchannel_to_buffer->num_of_guids = bytes / sizeof(GUID); + pchannel_to_buffer->guids = calloc(pchannel_to_buffer->num_of_guids, sizeof(GUID)); + + TRACE("number of GUIDs: %lu\n", pchannel_to_buffer->num_of_guids); + + if (!pchannel_to_buffer->guids) + { + hr = E_OUTOFMEMORY; + goto done; + } + hr = stream_read(stream, pchannel_to_buffer->guids, bytes); + + for (i = 0; i < pchannel_to_buffer->num_of_guids; i++) + TRACE("\tguids[%lu]: %s\n", i, debugstr_dmguid(&pchannel_to_buffer->guids[i])); + + if (FAILED(hr)) + goto done; + + list_add_tail(&This->pchannel_to_buffer_entries, &pchannel_to_buffer->entry); + pchannel_to_buffer = NULL; + break; + case FOURCC_LIST: + if (chunk.type == DMUS_FOURCC_UNFO_LIST) + TRACE("Unfo list in PChannelToBuffer is ignored\n"); + else + WARN("Unknown %s\n", debugstr_chunk(&chunk)); + break; + case MAKEFOURCC('p','b','g','d'): + FIXME("Undocumented %s\n", debugstr_chunk(&chunk)); + break; + default: + WARN("Unknown %s\n", debugstr_chunk(&chunk)); + break; + } + } +done: + if (FAILED(hr)) { + if (pchannel_to_buffer) + { + free(pchannel_to_buffer->guids); + free(pchannel_to_buffer); + } + return hr; + } + return S_OK; +} +static HRESULT parse_port_config_list(struct audio_path_config *This, IStream *stream, const struct chunk_entry *pcfl) +{ + struct chunk_entry chunk = { .parent = pcfl }; + struct audio_path_port_config *port_config = calloc(1, sizeof(*port_config)); + HRESULT hr; + + if (!port_config) + return E_OUTOFMEMORY; + + list_init(&port_config->pchannel_to_buffer_entries); + + while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) { + switch (chunk.id) + { + case DMUS_FOURCC_PORTCONFIG_ITEM: + hr = stream_chunk_get_data(stream, &chunk, &port_config->header, sizeof(port_config->header)); + if (FAILED(hr)) + goto done; + TRACE("Got PortConfig header:\n"); + TRACE("\tdwPChannelBase: %lu\n", port_config->header.dwPChannelBase); + TRACE("\tdwPChannelCount: %lu\n", port_config->header.dwPChannelCount); + TRACE("\tdwFlags: %lx\n", port_config->header.dwFlags); + TRACE("\tguidPort: %s\n", debugstr_dmguid(&port_config->header.guidPort)); + break; + case DMUS_FOURCC_PORTPARAMS_ITEM: + hr = stream_chunk_get_data(stream, &chunk, &port_config->params, sizeof(port_config->params)); + if (FAILED(hr)) + goto done; + TRACE("Got PortConfig params:\n"); + TRACE("\tdwSize: %lu\n", port_config->params.dwSize); + TRACE("\tdwValidParams: %lx\n", port_config->params.dwValidParams); + if (port_config->params.dwValidParams & DMUS_PORTPARAMS_VOICES) + TRACE("\tvoices: %lu\n", port_config->params.dwVoices); + if (port_config->params.dwValidParams & DMUS_PORTPARAMS_CHANNELGROUPS) + TRACE("\tchannel groups: %lu\n", port_config->params.dwChannelGroups); + if (port_config->params.dwValidParams & DMUS_PORTPARAMS_AUDIOCHANNELS) + TRACE("\taudio channels: %lu\n", port_config->params.dwAudioChannels); + if (port_config->params.dwValidParams & DMUS_PORTPARAMS_SAMPLERATE) + TRACE("\tsample rate: %lu\n", port_config->params.dwSampleRate); + if (port_config->params.dwValidParams & DMUS_PORTPARAMS_EFFECTS) + TRACE("\teffects: %lx\n", port_config->params.dwEffectFlags); + if (port_config->params.dwValidParams & DMUS_PORTPARAMS_SHARE) + TRACE("\tshare: %d\n", port_config->params.fShare); + if (port_config->params.dwValidParams & DMUS_PORTPARAMS_FEATURES) + TRACE("\tfeatures: %lx\n", port_config->params.dwFeatures); + break; + case FOURCC_LIST: + if (chunk.type == DMUS_FOURCC_DSBUFFER_LIST) + FIXME("DirectSound buffer descriptors is not supported\n"); + else if (chunk.type == DMUS_FOURCC_PCHANNELS_LIST) + { + hr = parse_pchannel_to_buffers_list(port_config, stream, &chunk); + if (FAILED(hr)) + goto done; + } + else if (chunk.type == DMUS_FOURCC_UNFO_LIST) + TRACE("Unfo list in PortConfig is ignored\n"); + else + WARN("Unknown %s\n", debugstr_chunk(&chunk)); + break; + default: + WARN("Unknown %s\n", debugstr_chunk(&chunk)); + } + } + +done: + if (FAILED(hr)) { + free(port_config); + return hr; + } + list_add_tail(&This->port_config_entries, &port_config->entry); + return S_OK; +} + +static HRESULT parse_port_configs_list(struct audio_path_config *This, IStream *stream, const struct chunk_entry *pcsl) +{ + struct chunk_entry chunk = { .parent = pcsl }; + HRESULT hr; + + while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) { + switch (MAKE_IDTYPE(chunk.id, chunk.type)) + { + case MAKE_IDTYPE(FOURCC_LIST, DMUS_FOURCC_PORTCONFIG_LIST): + hr = parse_port_config_list(This, stream, &chunk); + if (FAILED(hr)) + return hr; + break; + default: + WARN("Unknown %s\n", debugstr_chunk(&chunk)); + break; + } + } + return SUCCEEDED(hr) ? S_OK : hr; +}
/* IPersistStream */ static HRESULT WINAPI path_IPersistStream_Load(IPersistStream *iface, IStream *stream) { struct audio_path_config *This = impl_from_IPersistStream(iface); + struct chunk_entry riff = {0}, chunk = {0}; + HRESULT hr = S_OK; + + FIXME("(%p, %p): Loading\n", This, stream); + + if (!stream) + return E_POINTER; + + hr = stream_get_chunk(stream, &riff); + if (FAILED(hr)) { + WARN("Failed to get chunk %#lx.\n", hr); + return hr; + }
- FIXME("(%p, %p): Loading not implemented yet\n", This, stream); + if (MAKE_IDTYPE(riff.id, riff.type) != MAKE_IDTYPE(FOURCC_RIFF, DMUS_FOURCC_AUDIOPATH_FORM)) + { + WARN("loading failed: unexpected %s\n", debugstr_chunk(&riff)); + return E_UNEXPECTED; + }
- return IDirectMusicObject_ParseDescriptor(&This->dmobj.IDirectMusicObject_iface, stream, - &This->dmobj.desc); + if (FAILED(hr = dmobj_parsedescriptor(stream, &riff, &This->dmobj.desc, + DMUS_OBJ_OBJECT | DMUS_OBJ_VERSION | DMUS_OBJ_NAME | DMUS_OBJ_CATEGORY)) + || FAILED(hr = stream_reset_chunk_data(stream, &riff))) { + WARN("Failed to parse descriptor %#lx.\n", hr); + return hr; + } + This->dmobj.desc.guidClass = CLSID_DirectMusicAudioPathConfig; + This->dmobj.desc.dwValidData |= DMUS_OBJ_CLASS; + + chunk.parent = &riff; + while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) { + switch (chunk.id) { + case FOURCC_LIST: + if (chunk.type == DMUS_FOURCC_PORTCONFIGS_LIST) { + hr = parse_port_configs_list(This, stream, &chunk); + if (FAILED(hr)) + return hr; + } + else if (chunk.type == DMUS_FOURCC_DSBUFFER_LIST) + FIXME("buffer attributes are not supported\n"); + else if (chunk.type == MAKEFOURCC('p','a','p','d')) + FIXME("Undocumented %s\n", debugstr_chunk(&chunk)); + else if (chunk.type != DMUS_FOURCC_UNFO_LIST) + WARN("Unknown %s\n", debugstr_chunk(&chunk)); + break; + case DMUS_FOURCC_GUID_CHUNK: + case DMUS_FOURCC_VERSION_CHUNK: + /* Already parsed in dmobj_parsedescriptor. */ + break; + default: + WARN("Unknown %s\n", debugstr_chunk(&chunk)); + break; + } + } + TRACE("Finished parsing %#lx\n", hr); + return SUCCEEDED(hr) ? S_OK : hr; }
static const IPersistStreamVtbl persiststream_vtbl = { @@ -352,7 +594,11 @@ static HRESULT WINAPI path_config_IUnknown_QueryInterface(IUnknown *unk, REFIID static ULONG WINAPI path_config_IUnknown_AddRef(IUnknown *unk) { struct audio_path_config *This = impl_from_IUnknown(unk); - return InterlockedIncrement(&This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p): ref=%ld\n", This, ref); + + return ref; }
static ULONG WINAPI path_config_IUnknown_Release(IUnknown *unk) @@ -360,8 +606,24 @@ static ULONG WINAPI path_config_IUnknown_Release(IUnknown *unk) struct audio_path_config *This = impl_from_IUnknown(unk); ULONG ref = InterlockedDecrement(&This->ref);
- if (!ref) + TRACE("(%p): ref=%ld\n", This, ref); + + if (!ref) { + struct audio_path_port_config *i, *tmp; + LIST_FOR_EACH_ENTRY_SAFE(i, tmp, &This->port_config_entries, struct audio_path_port_config, entry) + { + struct audio_path_pchannel_to_buffer *j, *tmp2; + LIST_FOR_EACH_ENTRY_SAFE(j, tmp2, &i->pchannel_to_buffer_entries, struct audio_path_pchannel_to_buffer, entry) + { + list_remove(&j->entry); + free(j->guids); + free(j); + } + list_remove(&i->entry); + free(i); + } free(This); + } return ref; }
@@ -402,6 +664,8 @@ HRESULT create_dmaudiopath_config(REFIID riid, void **ppobj) obj->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl; obj->ref = 1;
+ list_init(&obj->port_config_entries); + hr = IUnknown_QueryInterface(&obj->unk, riid, ppobj); IUnknown_Release(&obj->unk); return hr;
From: Yuxuan Shui yshui@codeweavers.com
--- dlls/dmime/performance.c | 2 +- dlls/dmime/tests/dmime.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index bd596750f34..bce5f96352b 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -1654,7 +1654,7 @@ static HRESULT WINAPI performance_CreateAudioPath(IDirectMusicPerformance8 *ifac
FIXME("(%p, %p, %d, %p): stub\n", This, pSourceConfig, fActivate, ret_iface);
- if (!ret_iface) return E_POINTER; + if (!ret_iface || !pSourceConfig) return E_POINTER; if (!This->audio_paths_enabled) return DMUS_E_AUDIOPATH_INACTIVE;
create_dmaudiopath(&IID_IDirectMusicAudioPath, (void **)&pPath); diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index 2b7c744acdb..e9036511e9d 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -1256,6 +1256,7 @@ static void test_COM_performance(void) IDirectMusicPerformance *dmp = (IDirectMusicPerformance*)0xdeadbeef; IDirectMusicPerformance *dmp2; IDirectMusicPerformance8 *dmp8; + IDirectMusicAudioPath *dmap = NULL; ULONG refcount; HRESULT hr;
@@ -1284,6 +1285,9 @@ static void test_COM_performance(void) ok (refcount == 3, "refcount == %lu, expected 3\n", refcount); hr = IDirectMusicPerformance_QueryInterface(dmp, &IID_IDirectMusicPerformance8, (void**)&dmp8); ok(hr == S_OK, "QueryInterface for IID_IDirectMusicPerformance8 failed: %#lx\n", hr); + hr = IDirectMusicPerformance8_CreateAudioPath(dmp8, NULL, TRUE, &dmap); + ok(hr == E_POINTER, "Unexpected result from CreateAudioPath: %#lx\n", hr); + ok(dmap == NULL, "Unexpected dmap pointer\n"); refcount = IDirectMusicPerformance_Release(dmp); ok (refcount == 3, "refcount == %lu, expected 3\n", refcount); refcount = IDirectMusicPerformance8_Release(dmp8);
From: Yuxuan Shui yshui@codeweavers.com
--- dlls/dmime/audiopath.c | 35 +---------- dlls/dmime/dmime_private.h | 29 +++++++++ dlls/dmime/performance.c | 125 ++++++++++++++++++++++++++++++++++++- 3 files changed, 155 insertions(+), 34 deletions(-)
diff --git a/dlls/dmime/audiopath.c b/dlls/dmime/audiopath.c index 70985a261f8..721c28b2dc3 100644 --- a/dlls/dmime/audiopath.c +++ b/dlls/dmime/audiopath.c @@ -32,30 +32,6 @@ struct IDirectMusicAudioPathImpl { BOOL fActive; };
-struct audio_path_pchannel_to_buffer { - struct list entry; - DMUS_IO_PCHANNELTOBUFFER_HEADER header; - - ULONG num_of_guids; - GUID *guids; -}; - -struct audio_path_port_config { - struct list entry; - DMUS_IO_PORTCONFIG_HEADER header; - DMUS_PORTPARAMS8 params; - - struct list pchannel_to_buffer_entries; -}; - -struct audio_path_config { - IUnknown unk; - struct dmobject dmobj; - LONG ref; - - struct list port_config_entries; -}; - static inline struct IDirectMusicAudioPathImpl *impl_from_IDirectMusicAudioPath(IDirectMusicAudioPath *iface) { return CONTAINING_RECORD(iface, struct IDirectMusicAudioPathImpl, IDirectMusicAudioPath_iface); @@ -562,14 +538,9 @@ static const IPersistStreamVtbl persiststream_vtbl = { unimpl_IPersistStream_GetSizeMax };
-static struct audio_path_config *impl_from_IUnknown(IUnknown *iface) -{ - return CONTAINING_RECORD(iface, struct audio_path_config, unk); -} - static HRESULT WINAPI path_config_IUnknown_QueryInterface(IUnknown *unk, REFIID riid, void **ppobj) { - struct audio_path_config *This = impl_from_IUnknown(unk); + struct audio_path_config *This = path_config_from_IUnknown(unk);
TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
@@ -593,7 +564,7 @@ static HRESULT WINAPI path_config_IUnknown_QueryInterface(IUnknown *unk, REFIID
static ULONG WINAPI path_config_IUnknown_AddRef(IUnknown *unk) { - struct audio_path_config *This = impl_from_IUnknown(unk); + struct audio_path_config *This = path_config_from_IUnknown(unk); ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p): ref=%ld\n", This, ref); @@ -603,7 +574,7 @@ static ULONG WINAPI path_config_IUnknown_AddRef(IUnknown *unk)
static ULONG WINAPI path_config_IUnknown_Release(IUnknown *unk) { - struct audio_path_config *This = impl_from_IUnknown(unk); + struct audio_path_config *This = path_config_from_IUnknown(unk); ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p): ref=%ld\n", This, ref); diff --git a/dlls/dmime/dmime_private.h b/dlls/dmime/dmime_private.h index 7b744419c38..7fcf264b92f 100644 --- a/dlls/dmime/dmime_private.h +++ b/dlls/dmime/dmime_private.h @@ -105,6 +105,35 @@ typedef struct _DMUS_PRIVATE_TEMPO_PLAY_STATE { DWORD dummy; } DMUS_PRIVATE_TEMPO_PLAY_STATE, *LPDMUS_PRIVATE_TEMPO_PLAY_STATE;
+struct audio_path_pchannel_to_buffer { + struct list entry; + DMUS_IO_PCHANNELTOBUFFER_HEADER header; + + ULONG num_of_guids; + GUID *guids; +}; + +struct audio_path_port_config { + struct list entry; + DMUS_IO_PORTCONFIG_HEADER header; + DMUS_PORTPARAMS8 params; + + struct list pchannel_to_buffer_entries; +}; + +struct audio_path_config { + IUnknown unk; + struct dmobject dmobj; + LONG ref; + + struct list port_config_entries; +}; + +static inline struct audio_path_config *path_config_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, struct audio_path_config, unk); +} + /***************************************************************************** * Misc. */ diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index bce5f96352b..646d3a08013 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -1650,17 +1650,138 @@ static HRESULT WINAPI performance_CreateAudioPath(IDirectMusicPerformance8 *ifac IUnknown *pSourceConfig, BOOL fActivate, IDirectMusicAudioPath **ret_iface) { struct performance *This = impl_from_IDirectMusicPerformance8(iface); + struct audio_path_config *audio_path_config; + struct list *first_port_config, *first_pchannel_to_buffer; + struct audio_path_port_config *port_config; + struct audio_path_pchannel_to_buffer *pchannel_to_buffer; IDirectMusicAudioPath *pPath; + IDirectMusicObject *dmo; + IDirectSoundBuffer *buffer, *primary_buffer; + DMUS_OBJECTDESC objDesc; + DMUS_PORTPARAMS8 port_params; + HRESULT hr; + WAVEFORMATEX format; + DSBUFFERDESC desc; + GUID *buffer_guids;
- FIXME("(%p, %p, %d, %p): stub\n", This, pSourceConfig, fActivate, ret_iface); + FIXME("(%p, %p, %d, %p): semi-stub\n", This, pSourceConfig, fActivate, ret_iface);
if (!ret_iface || !pSourceConfig) return E_POINTER; if (!This->audio_paths_enabled) return DMUS_E_AUDIOPATH_INACTIVE;
+ hr = IUnknown_QueryInterface(pSourceConfig, &IID_IDirectMusicObject, (void **)&dmo); + if (FAILED(hr)) + return hr; + + hr = IDirectMusicObject_GetDescriptor(dmo, &objDesc); + IDirectMusicObject_Release(dmo); + if (FAILED(hr)) + return hr; + + if (!IsEqualCLSID(&objDesc.guidClass, &CLSID_DirectMusicAudioPathConfig)) + { + ERR("Unexpected object class %s for source config.\n", debugstr_dmguid(&objDesc.guidClass)); + return E_INVALIDARG; + } + + audio_path_config = path_config_from_IUnknown(pSourceConfig); + first_port_config = list_head(&audio_path_config->port_config_entries); + if (list_next(&audio_path_config->port_config_entries, first_port_config)) + FIXME("Only one port config supported. %p -> %p\n", first_port_config, list_next(&audio_path_config->port_config_entries, first_port_config)); + port_config = LIST_ENTRY(first_port_config, struct audio_path_port_config, entry); + first_pchannel_to_buffer = list_head(&port_config->pchannel_to_buffer_entries); + if (list_next(&port_config->pchannel_to_buffer_entries, first_pchannel_to_buffer)) + FIXME("Only one pchannel to buffer entry supported.\n"); + pchannel_to_buffer = LIST_ENTRY(first_pchannel_to_buffer, struct audio_path_pchannel_to_buffer, entry); + + /* Secondary buffer description */ + memset(&format, 0, sizeof(format)); + format.wFormatTag = WAVE_FORMAT_PCM; + format.nChannels = 1; + format.nSamplesPerSec = 44000; + format.nAvgBytesPerSec = 44000*2; + format.nBlockAlign = 2; + format.wBitsPerSample = 16; + format.cbSize = 0; + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DSBCAPS_CTRLFX | DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS; + desc.dwBufferBytes = DSBSIZE_MIN; + desc.dwReserved = 0; + desc.lpwfxFormat = &format; + desc.guid3DAlgorithm = GUID_NULL; + + buffer_guids = pchannel_to_buffer->guids; + if (pchannel_to_buffer->num_of_guids == 2) + { + if ((!IsEqualGUID(&buffer_guids[0], &GUID_Buffer_Reverb) && !IsEqualGUID(&buffer_guids[0], &GUID_Buffer_Stereo)) || + (!IsEqualGUID(&buffer_guids[1], &GUID_Buffer_Reverb) && !IsEqualGUID(&buffer_guids[1], &GUID_Buffer_Stereo))) + FIXME("Only a stereo plus reverb buffer is supported\n"); + else + { + desc.dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY; + format.nChannels = 2; + format.nBlockAlign *= 2; + format.nAvgBytesPerSec *=2; + } + } + else if (pchannel_to_buffer->num_of_guids == 1) + { + if (IsEqualGUID(buffer_guids, &GUID_Buffer_Stereo)) + { + desc.dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY; + format.nChannels = 2; + format.nBlockAlign *= 2; + format.nAvgBytesPerSec *=2; + } + else if (IsEqualGUID(buffer_guids, &GUID_Buffer_3D_Dry)) + desc.dwFlags |= DSBCAPS_CTRL3D | DSBCAPS_CTRLFREQUENCY | DSBCAPS_MUTE3DATMAXDISTANCE; + else if (IsEqualGUID(buffer_guids, &GUID_Buffer_Mono)) + desc.dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY; + else + FIXME("Unsupported buffer guid %s\n", debugstr_dmguid(buffer_guids)); + } + else + FIXME("Multiple buffers not supported\n"); + + port_params = port_config->params; + if (!(port_params.dwValidParams & DMUS_PORTPARAMS_CHANNELGROUPS)) + { + port_params.dwValidParams |= DMUS_PORTPARAMS_CHANNELGROUPS; + port_params.dwChannelGroups = (port_config->header.dwPChannelCount + 15) / 16; + } + if (!(port_params.dwValidParams & DMUS_PORTPARAMS_AUDIOCHANNELS)) + { + port_params.dwValidParams |= DMUS_PORTPARAMS_AUDIOCHANNELS; + port_params.dwAudioChannels = format.nChannels; + } + hr = perf_dmport_create(This, &port_config->params); + if (FAILED(hr)) + return hr; + + hr = IDirectSound_CreateSoundBuffer(This->dsound, &desc, &buffer, NULL); + if (FAILED(hr)) + return DSERR_BUFFERLOST; + + /* Update description for creating primary buffer */ + desc.dwFlags |= DSBCAPS_PRIMARYBUFFER; + desc.dwFlags &= ~DSBCAPS_CTRLFX; + desc.dwBufferBytes = 0; + desc.lpwfxFormat = NULL; + + hr = IDirectSound_CreateSoundBuffer(This->dsound, &desc, &primary_buffer, NULL); + if (FAILED(hr)) { + IDirectSoundBuffer_Release(buffer); + return DSERR_BUFFERLOST; + } + create_dmaudiopath(&IID_IDirectMusicAudioPath, (void **)&pPath); set_audiopath_perf_pointer(pPath, iface); + set_audiopath_dsound_buffer(pPath, buffer); + set_audiopath_primary_dsound_buffer(pPath, primary_buffer); + TRACE(" returning IDirectMusicAudioPath interface at %p.\n", *ret_iface);
- /** TODO */ *ret_iface = pPath; return IDirectMusicAudioPath_Activate(*ret_iface, fActivate); }
Rémi Bernon (@rbernon) commented about dlls/dmime/audiopath.c:
BOOL fActive;
};
+struct audio_path_config {
```suggestion:-0+0 struct audio_path_config { ```
I know the file isn't written like that but I don't think we should rely on its current style which is for most part in dmusic, historical. Instead prefer and move toward a canonical Wine style.
Rémi Bernon (@rbernon) commented about dlls/dmime/audiopath.c:
BOOL fActive;
};
+struct audio_path_config {
- IUnknown unk;
```suggestion:-0+0 IUnknown IUnknown_iface; ```
Like it's done everywhere else in Wine.
Rémi Bernon (@rbernon) commented about dlls/dmime/audiopath.c:
unimpl_IPersistStream_GetSizeMax
};
+static struct audio_path_config *impl_from_IUnknown(IUnknown *iface) +{
- return CONTAINING_RECORD(iface, struct audio_path_config, unk);
+}
+static HRESULT WINAPI path_config_IUnknown_QueryInterface(IUnknown *unk, REFIID riid, void **ppobj)
```suggestion:-0+0 static HRESULT WINAPI path_config_IUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppobj) ```
Ditto for the other functions, the parameter is consistently named iface everywhere else.
Rémi Bernon (@rbernon) commented about dlls/dmime/audiopath.c:
+static HRESULT WINAPI path_config_IUnknown_QueryInterface(IUnknown *unk, REFIID riid, void **ppobj) +{
- struct audio_path_config *This = impl_from_IUnknown(unk);
- TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
- *ppobj = NULL;
- if (IsEqualIID (riid, &IID_IUnknown))
*ppobj = &This->unk;
- else if (IsEqualIID (riid, &IID_IDirectMusicObject))
*ppobj = &This->dmobj.IDirectMusicObject_iface;
- else if (IsEqualIID (riid, &IID_IPersistStream))
*ppobj = &This->dmobj.IPersistStream_iface;
- if (*ppobj) {
```suggestion:-0+0 if (*ppobj) { ```
Rémi Bernon (@rbernon) commented about dlls/dmime/audiopath.c:
+{
- struct audio_path_config *This = impl_from_IUnknown(unk);
- return InterlockedIncrement(&This->ref);
+}
+static ULONG WINAPI path_config_IUnknown_Release(IUnknown *unk) +{
- struct audio_path_config *This = impl_from_IUnknown(unk);
- ULONG ref = InterlockedDecrement(&This->ref);
- if (!ref)
free(This);
- return ref;
+}
+static const IUnknownVtbl path_config_unk_vtbl = {
```suggestion:-0+0 static const IUnknownVtbl path_config_unk_vtbl = { ```
Rémi Bernon (@rbernon) commented about dlls/dmime/audiopath.c:
obj->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl;
hr = IDirectMusicAudioPath_QueryInterface(&obj->IDirectMusicAudioPath_iface, riid, ppobj); IDirectMusicAudioPath_Release(&obj->IDirectMusicAudioPath_iface); return hr;
}
+HRESULT create_dmaudiopath_config(REFIID riid, void **ppobj) +{
- struct audio_path_config *obj;
- HRESULT hr;
- *ppobj = NULL;
- obj = calloc(1, sizeof(*obj));
- if (!obj)
return E_OUTOFMEMORY;
```suggestion:-2+0 if (!(obj = calloc(1, sizeof(*obj)))) return E_OUTOFMEMORY; ```
Moving toward consistent style is IMO better.
Rémi Bernon (@rbernon) commented about dlls/dmime/audiopath.c:
/* IPersistStream */ static HRESULT WINAPI path_IPersistStream_Load(IPersistStream *iface, IStream *stream)
```suggestion:-0+0 static HRESULT WINAPI path_config_IPersistStream_Load(IPersistStream *iface, IStream *stream) ```
Would probably be better to rename `path_IDirectMusicObject_ParseDescriptor` too.
Rémi Bernon (@rbernon) commented about dlls/dmime/audiopath.c:
BOOL fActive;
};
+struct audio_path_pchannel_to_buffer {
```suggestion:-0+0 struct audio_path_pchannel_to_buffer { ```
Ditto everywhere else braces are used.
Rémi Bernon (@rbernon) commented about dlls/dmime/audiopath.c:
dmobj_IDirectMusicObject_SetDescriptor, path_IDirectMusicObject_ParseDescriptor
}; +static HRESULT parse_pchannel_to_buffers_list(struct audio_path_port_config *This, IStream *stream, const struct chunk_entry *pchl)
Missing blank line before.
Rémi Bernon (@rbernon) commented about dlls/dmime/dmime_private.h:
- struct list pchannel_to_buffer_entries;
+};
+struct audio_path_config {
- IUnknown unk;
- struct dmobject dmobj;
- LONG ref;
- struct list port_config_entries;
+};
+static inline struct audio_path_config *path_config_from_IUnknown(IUnknown *iface) +{
- return CONTAINING_RECORD(iface, struct audio_path_config, unk);
+}
There was a lot of struct sharing like that before, I don't think it's a good idea for refactorability. Exposing a few helper functions and manipulating object through their COM interface pointers instead provides better isolation between components.
Rémi Bernon (@rbernon) commented about dlls/dmime/audiopath.c:
WARN("Unknown %s\n", debugstr_chunk(&chunk));
break;
}
- }
+done:
- if (FAILED(hr)) {
if (pchannel_to_buffer)
{
free(pchannel_to_buffer->guids);
free(pchannel_to_buffer);
}
return hr;
- }
- return S_OK;
+} +static HRESULT parse_port_config_list(struct audio_path_config *This, IStream *stream, const struct chunk_entry *pcfl)
```suggestion:-0+0
static HRESULT parse_port_config_list(struct audio_path_config *This, IStream *stream, const struct chunk_entry *parent) ```
Note that we try to avoid hungarian notation or abbreviations in new code.
Rémi Bernon (@rbernon) commented about dlls/dmime/audiopath.c:
if (bytes % sizeof(GUID))
{
WARN("Invalid size of GUIDs array\n");
hr = E_FAIL;
goto done;
}
pchannel_to_buffer->num_of_guids = bytes / sizeof(GUID);
pchannel_to_buffer->guids = calloc(pchannel_to_buffer->num_of_guids, sizeof(GUID));
TRACE("number of GUIDs: %lu\n", pchannel_to_buffer->num_of_guids);
if (!pchannel_to_buffer->guids)
{
hr = E_OUTOFMEMORY;
goto done;
}
Imo a flexible guids array member would make the logic simpler and let you have a single alloc here.
Rémi Bernon (@rbernon) commented about dlls/dmime/audiopath.c:
break;
case FOURCC_LIST:
if (chunk.type == DMUS_FOURCC_UNFO_LIST)
TRACE("Unfo list in PChannelToBuffer is ignored\n");
else
WARN("Unknown %s\n", debugstr_chunk(&chunk));
break;
case MAKEFOURCC('p','b','g','d'):
FIXME("Undocumented %s\n", debugstr_chunk(&chunk));
break;
default:
WARN("Unknown %s\n", debugstr_chunk(&chunk));
break;
}
- }
+done:
You don't need a label here, break should do it.
Rémi Bernon (@rbernon) commented about dlls/dmime/audiopath.c:
break;
default:
WARN("Unknown %s\n", debugstr_chunk(&chunk));
break;
}
- }
+done:
- if (FAILED(hr)) {
if (pchannel_to_buffer)
{
free(pchannel_to_buffer->guids);
free(pchannel_to_buffer);
}
return hr;
- }
- return S_OK;
You can combine the ifs with && and return hr. Also with a single alloc you could even get rid of the `if (pchannel_to_buffer)`.
Rémi Bernon (@rbernon) commented about dlls/dmime/audiopath.c:
TRACE("Unfo list in PortConfig is ignored\n");
else
WARN("Unknown %s\n", debugstr_chunk(&chunk));
break;
default:
WARN("Unknown %s\n", debugstr_chunk(&chunk));
}
- }
+done:
- if (FAILED(hr)) {
free(port_config);
return hr;
- }
- list_add_tail(&This->port_config_entries, &port_config->entry);
- return S_OK;
```suggestion:-9+0 }
if (FAILED(hr)) break; }
if (FAILED(hr)) free(port_config); else list_add_tail(&This->port_config_entries, &port_config->entry); return hr; ```
Like it's done in other recent dmusic changes. I don't really mind either but I prefer a consistent code style.
Rémi Bernon (@rbernon) commented about dlls/dmime/audiopath.c:
if (FAILED(hr))
goto done;
}
else if (chunk.type == DMUS_FOURCC_UNFO_LIST)
TRACE("Unfo list in PortConfig is ignored\n");
else
WARN("Unknown %s\n", debugstr_chunk(&chunk));
break;
default:
WARN("Unknown %s\n", debugstr_chunk(&chunk));
}
- }
+done:
- if (FAILED(hr)) {
free(port_config);
Freeing is not enough, you might leak partially parsed data and pchannel_to_buffers entries. Elsewhere I added `<object>_destroy` helpers that I used when needed to delete their entries properly and which can be used in `path_config_IUnknown_Release` too.
Rémi Bernon (@rbernon) commented about dlls/dmime/audiopath.c:
- chunk.parent = &riff;
- while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
switch (chunk.id) {
case FOURCC_LIST:
if (chunk.type == DMUS_FOURCC_PORTCONFIGS_LIST) {
hr = parse_port_configs_list(This, stream, &chunk);
if (FAILED(hr))
return hr;
}
else if (chunk.type == DMUS_FOURCC_DSBUFFER_LIST)
FIXME("buffer attributes are not supported\n");
else if (chunk.type == MAKEFOURCC('p','a','p','d'))
FIXME("Undocumented %s\n", debugstr_chunk(&chunk));
else if (chunk.type != DMUS_FOURCC_UNFO_LIST)
WARN("Unknown %s\n", debugstr_chunk(&chunk));
break;
Using `switch (MAKE_IDTYPE(chunk.id, chunk.type))` like you did above, let you put every case on the same switch level and IMO makes the code nicer to read.
Rémi Bernon (@rbernon) commented about dlls/dmime/audiopath.c:
struct audio_path_config *This = impl_from_IUnknown(unk); ULONG ref = InterlockedDecrement(&This->ref);
- if (!ref)
- TRACE("(%p): ref=%ld\n", This, ref);
- if (!ref) {
struct audio_path_port_config *i, *tmp;
```suggestion:-0+0 struct audio_path_port_config *config, *next; ```
We prefer longer names in general except for loop integer indices. The safe pointer is also more consistently named "next" or "next_<object>".
Rémi Bernon (@rbernon) commented about dlls/dmime/audiopath.c:
TRACE("\tdwSize: %lu\n", port_config->params.dwSize);
TRACE("\tdwValidParams: %lx\n", port_config->params.dwValidParams);
if (port_config->params.dwValidParams & DMUS_PORTPARAMS_VOICES)
TRACE("\tvoices: %lu\n", port_config->params.dwVoices);
if (port_config->params.dwValidParams & DMUS_PORTPARAMS_CHANNELGROUPS)
TRACE("\tchannel groups: %lu\n", port_config->params.dwChannelGroups);
if (port_config->params.dwValidParams & DMUS_PORTPARAMS_AUDIOCHANNELS)
TRACE("\taudio channels: %lu\n", port_config->params.dwAudioChannels);
if (port_config->params.dwValidParams & DMUS_PORTPARAMS_SAMPLERATE)
TRACE("\tsample rate: %lu\n", port_config->params.dwSampleRate);
if (port_config->params.dwValidParams & DMUS_PORTPARAMS_EFFECTS)
TRACE("\teffects: %lx\n", port_config->params.dwEffectFlags);
if (port_config->params.dwValidParams & DMUS_PORTPARAMS_SHARE)
TRACE("\tshare: %d\n", port_config->params.fShare);
if (port_config->params.dwValidParams & DMUS_PORTPARAMS_FEATURES)
TRACE("\tfeatures: %lx\n", port_config->params.dwFeatures);
Michael might say otherwise but outside of local changes for development, I don't think it's very useful to trace data that's not used. A simple FIXME would be enough for now.
Sorry for the lot of nitpicks but I think consistency matters.
On Wed Jan 17 08:16:30 2024 +0000, Rémi Bernon wrote:
static HRESULT parse_port_config_list(struct audio_path_config *This, IStream *stream, const struct chunk_entry *parent)
Note that we try to avoid hungarian notation or abbreviations in new code.
`pcfl` is referring to the chunk type, it's not hungarian.
On Wed Jan 17 08:19:23 2024 +0000, Rémi Bernon wrote:
~~You don't need a label here, break should do it.~~ Nvm it's a loop, but labels aren't used in the other place that parsing pattern is used now.
What's your suggestion here?
On Wed Jan 17 08:16:32 2024 +0000, Rémi Bernon wrote:
You can combine the ifs with && and return hr. Also with a single alloc you could even get rid of the `if (pchannel_to_buffer)`.
I can't, `!FAILED(hr)` doesn't mean `hr` is `S_OK`. `stream_get_chunk` returns `S_FALSE` for EOF.
On Wed Jan 17 08:16:37 2024 +0000, Rémi Bernon wrote:
Using `switch (MAKE_IDTYPE(chunk.id, chunk.type))` like you did above, let you put every case on the same switch level and IMO makes the code nicer to read.
What about chunks without a type (non-list chunks)?