From: Yuxuan Shui yshui@codeweavers.com
--- dlls/dmime/audiopath.c | 83 ++++++++++++++++++++++++++++++++++++++ dlls/dmime/dmime_private.h | 2 + dlls/dmime/performance.c | 53 +++++++++++++++++++++++- 3 files changed, 136 insertions(+), 2 deletions(-)
diff --git a/dlls/dmime/audiopath.c b/dlls/dmime/audiopath.c index 62c9968fd5f..2e6a916136f 100644 --- a/dlls/dmime/audiopath.c +++ b/dlls/dmime/audiopath.c @@ -645,6 +645,89 @@ static const IUnknownVtbl path_config_unk_vtbl = path_config_IUnknown_Release, };
+HRESULT path_config_get_audio_path_params(IUnknown *iface, WAVEFORMATEX *format, DSBUFFERDESC *desc, DMUS_PORTPARAMS *params) +{ + struct audio_path_config *This = impl_from_IUnknown(iface); + 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; + GUID *guids; + + first_port_config = list_head(&This->port_config_entries); + if (list_next(&This->port_config_entries, first_port_config)) + FIXME("Only one port config supported. %p -> %p\n", first_port_config, list_next(&This->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; + + guids = pchannel_to_buffer->guids; + if (pchannel_to_buffer->header.dwBufferCount == 2) + { + if ((!IsEqualGUID(&guids[0], &GUID_Buffer_Reverb) && !IsEqualGUID(&guids[0], &GUID_Buffer_Stereo)) || + (!IsEqualGUID(&guids[1], &GUID_Buffer_Reverb) && !IsEqualGUID(&guids[1], &GUID_Buffer_Stereo)) || + IsEqualGUID(&guids[0], &guids[1])) + 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->header.dwBufferCount == 1) + { + if (IsEqualGUID(guids, &GUID_Buffer_Stereo)) + { + desc->dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY; + format->nChannels = 2; + format->nBlockAlign *= 2; + format->nAvgBytesPerSec *= 2; + } + else if (IsEqualGUID(guids, &GUID_Buffer_3D_Dry)) + desc->dwFlags |= DSBCAPS_CTRL3D | DSBCAPS_CTRLFREQUENCY | DSBCAPS_MUTE3DATMAXDISTANCE; + else if (IsEqualGUID(guids, &GUID_Buffer_Mono)) + desc->dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY; + else + FIXME("Unsupported buffer guid %s\n", debugstr_dmguid(guids)); + } + else + FIXME("Multiple buffers not supported\n"); + + *params = port_config->params; + if (!(params->dwValidParams & DMUS_PORTPARAMS_CHANNELGROUPS)) + { + params->dwValidParams |= DMUS_PORTPARAMS_CHANNELGROUPS; + params->dwChannelGroups = (port_config->header.dwPChannelCount + 15) / 16; + } + if (!(params->dwValidParams & DMUS_PORTPARAMS_AUDIOCHANNELS)) + { + params->dwValidParams |= DMUS_PORTPARAMS_AUDIOCHANNELS; + params->dwAudioChannels = format->nChannels; + } + return S_OK; +} + /* for ClassFactory */ HRESULT create_dmaudiopath(REFIID riid, void **ppobj) { diff --git a/dlls/dmime/dmime_private.h b/dlls/dmime/dmime_private.h index 7b744419c38..96ccd5daf8b 100644 --- a/dlls/dmime/dmime_private.h +++ b/dlls/dmime/dmime_private.h @@ -93,6 +93,8 @@ extern HRESULT performance_send_segment_tick(IDirectMusicPerformance8 *iface, MU extern HRESULT performance_send_segment_end(IDirectMusicPerformance8 *iface, MUSIC_TIME music_time, IDirectMusicSegmentState *state, BOOL abort);
+HRESULT path_config_get_audio_path_params(IUnknown *iface, WAVEFORMATEX *format, DSBUFFERDESC *desc, DMUS_PORTPARAMS *params); + /***************************************************************************** * Auxiliary definitions */ diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index bce5f96352b..08d74a81c25 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -1651,16 +1651,65 @@ static HRESULT WINAPI performance_CreateAudioPath(IDirectMusicPerformance8 *ifac { struct performance *This = impl_from_IDirectMusicPerformance8(iface); IDirectMusicAudioPath *pPath; + IDirectMusicObject *dmo; + IDirectSoundBuffer *buffer, *primary_buffer; + DMUS_OBJECTDESC objDesc; + DMUS_PORTPARAMS8 port_params; + HRESULT hr; + WAVEFORMATEX format; + DSBUFFERDESC desc;
- 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; + } + + hr = path_config_get_audio_path_params(pSourceConfig, &format, &desc, &port_params); + if (FAILED(hr)) + return hr; + + hr = perf_dmport_create(This, &port_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); }