dmime: Semi-support creating an audio path from config.

This commit is contained in:
Yuxuan Shui 2024-01-18 12:59:49 +00:00 committed by Alexandre Julliard
parent e9a52308bb
commit 8daf207bf7
3 changed files with 136 additions and 2 deletions

View file

@ -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)
{

View file

@ -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
*/

View file

@ -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);
}