2 * Copyright (c) 2018 Ethan Lee for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define NONAMELESSUNION
26 #if XACT3_VER < 0x0300
36 #include "wine/debug.h"
37 #include "wine/rbtree.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(xaudio2
);
41 #if XACT3_VER < 0x0300
42 #define IID_IXACT3Engine IID_IXACTEngine
43 #define IXACT3Cue IXACTCue
44 #define IXACT3CueVtbl IXACTCueVtbl
45 #define IXACT3Engine IXACTEngine
46 #define IXACT3EngineVtbl IXACTEngineVtbl
47 #define IXACT3Engine_QueryInterface IXACTEngine_QueryInterface
48 #define IXACT3SoundBank IXACTSoundBank
49 #define IXACT3SoundBankVtbl IXACTSoundBankVtbl
50 #define IXACT3Wave IXACTWave
51 #define IXACT3WaveVtbl IXACTWaveVtbl
52 #define IXACT3WaveBank IXACTWaveBank
53 #define IXACT3WaveBankVtbl IXACTWaveBankVtbl
56 #define XACTNOTIFICATIONTYPE_MAX 19 /* XACTNOTIFICATIONTYPE_WAVEBANKSTREAMING_INVALIDCONTENT + 1 */
60 struct wine_rb_entry entry
;
65 typedef struct _XACT3EngineImpl
{
66 IXACT3Engine IXACT3Engine_iface
;
68 FACTAudioEngine
*fact_engine
;
70 XACT_READFILE_CALLBACK pReadFile
;
71 XACT_GETOVERLAPPEDRESULT_CALLBACK pGetOverlappedResult
;
72 XACT_NOTIFICATION_CALLBACK notification_callback
;
74 void *contexts
[XACTNOTIFICATIONTYPE_MAX
];
75 struct wine_rb_tree wrapper_lookup
;
76 CRITICAL_SECTION wrapper_lookup_cs
;
79 static int wrapper_lookup_compare(const void *key
, const struct wine_rb_entry
*entry
)
81 struct wrapper_lookup
*lookup
= WINE_RB_ENTRY_VALUE(entry
, struct wrapper_lookup
, entry
);
83 return (key
> lookup
->fact
) - (key
< lookup
->fact
);
86 static void wrapper_lookup_destroy(struct wine_rb_entry
*entry
, void *context
)
88 struct wrapper_lookup
*lookup
= WINE_RB_ENTRY_VALUE(entry
, struct wrapper_lookup
, entry
);
90 HeapFree(GetProcessHeap(), 0, lookup
);
93 static void wrapper_remove_entry(XACT3EngineImpl
*engine
, void *key
)
95 struct wrapper_lookup
*lookup
;
96 struct wine_rb_entry
*entry
;
98 EnterCriticalSection(&engine
->wrapper_lookup_cs
);
100 entry
= wine_rb_get(&engine
->wrapper_lookup
, key
);
103 LeaveCriticalSection(&engine
->wrapper_lookup_cs
);
105 WARN("cannot find key in wrapper lookup\n");
109 wine_rb_remove(&engine
->wrapper_lookup
, entry
);
111 LeaveCriticalSection(&engine
->wrapper_lookup_cs
);
113 lookup
= WINE_RB_ENTRY_VALUE(entry
, struct wrapper_lookup
, entry
);
114 HeapFree(GetProcessHeap(), 0, lookup
);
118 static HRESULT
wrapper_add_entry(XACT3EngineImpl
*engine
, void *fact
, void *xact
)
120 struct wrapper_lookup
*lookup
;
123 lookup
= HeapAlloc(GetProcessHeap(), 0, sizeof(*lookup
));
126 ERR("Failed to allocate wrapper_lookup!\n");
127 return E_OUTOFMEMORY
;
132 EnterCriticalSection(&engine
->wrapper_lookup_cs
);
133 ret
= wine_rb_put(&engine
->wrapper_lookup
, lookup
->fact
, &lookup
->entry
);
134 LeaveCriticalSection(&engine
->wrapper_lookup_cs
);
138 WARN("wrapper_lookup already present in the tree??\n");
139 HeapFree(GetProcessHeap(), 0, lookup
);
145 /* Must be protected by engine->wrapper_lookup_cs */
146 static void* wrapper_find_entry(XACT3EngineImpl
*engine
, void *faudio
)
148 struct wrapper_lookup
*lookup
;
149 struct wine_rb_entry
*entry
;
151 entry
= wine_rb_get(&engine
->wrapper_lookup
, faudio
);
154 lookup
= WINE_RB_ENTRY_VALUE(entry
, struct wrapper_lookup
, entry
);
158 WARN("cannot find interface in wrapper lookup\n");
162 typedef struct _XACT3CueImpl
{
163 IXACT3Cue IXACT3Cue_iface
;
165 XACT3EngineImpl
*engine
;
168 static inline XACT3CueImpl
*impl_from_IXACT3Cue(IXACT3Cue
*iface
)
170 return CONTAINING_RECORD(iface
, XACT3CueImpl
, IXACT3Cue_iface
);
173 static HRESULT WINAPI
IXACT3CueImpl_Play(IXACT3Cue
*iface
)
175 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
177 TRACE("(%p)\n", iface
);
179 return FACTCue_Play(This
->fact_cue
);
182 static HRESULT WINAPI
IXACT3CueImpl_Stop(IXACT3Cue
*iface
, DWORD dwFlags
)
184 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
186 TRACE("(%p)->(%lu)\n", iface
, dwFlags
);
188 return FACTCue_Stop(This
->fact_cue
, dwFlags
);
191 static HRESULT WINAPI
IXACT3CueImpl_GetState(IXACT3Cue
*iface
, DWORD
*pdwState
)
193 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
195 TRACE("(%p)->(%p)\n", iface
, pdwState
);
197 return FACTCue_GetState(This
->fact_cue
, (uint32_t *)pdwState
);
200 static HRESULT WINAPI
IXACT3CueImpl_Destroy(IXACT3Cue
*iface
)
202 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
205 TRACE("(%p)\n", iface
);
207 ret
= FACTCue_Destroy(This
->fact_cue
);
209 WARN("FACTCue_Destroy returned %d\n", ret
);
210 wrapper_remove_entry(This
->engine
, This
->fact_cue
);
211 HeapFree(GetProcessHeap(), 0, This
);
215 #if XACT3_VER < 0x0300
217 static HRESULT WINAPI
IXACT3CueImpl_GetChannelMap(IXACT3Cue
*iface
,
218 XACTCHANNELMAP
*map
, DWORD size
, DWORD
*needed_size
)
220 FIXME("(%p)->(%p, %lu, %p)\n", iface
, map
, size
, needed_size
);
225 static HRESULT WINAPI
IXACT3CueImpl_SetChannelMap(IXACT3Cue
*iface
, XACTCHANNELMAP
*map
)
227 FIXME("(%p)->(%p)\n", iface
, map
);
232 static HRESULT WINAPI
IXACT3CueImpl_GetChannelVolume(IXACT3Cue
*iface
, XACTCHANNELVOLUME
*volume
)
234 FIXME("(%p)->(%p)\n", iface
, volume
);
239 static HRESULT WINAPI
IXACT3CueImpl_SetChannelVolume(IXACT3Cue
*iface
, XACTCHANNELVOLUME
*volume
)
241 FIXME("(%p)->(%p)\n", iface
, volume
);
248 static HRESULT WINAPI
IXACT3CueImpl_SetMatrixCoefficients(IXACT3Cue
*iface
,
249 UINT32 uSrcChannelCount
, UINT32 uDstChannelCount
,
250 float *pMatrixCoefficients
)
252 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
254 TRACE("(%p)->(%u, %u, %p)\n", iface
, uSrcChannelCount
, uDstChannelCount
,
255 pMatrixCoefficients
);
257 return FACTCue_SetMatrixCoefficients(This
->fact_cue
, uSrcChannelCount
,
258 uDstChannelCount
, pMatrixCoefficients
);
261 static XACTVARIABLEINDEX WINAPI
IXACT3CueImpl_GetVariableIndex(IXACT3Cue
*iface
,
262 PCSTR szFriendlyName
)
264 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
266 TRACE("(%p)->(%s)\n", iface
, szFriendlyName
);
268 return FACTCue_GetVariableIndex(This
->fact_cue
, szFriendlyName
);
271 static HRESULT WINAPI
IXACT3CueImpl_SetVariable(IXACT3Cue
*iface
,
272 XACTVARIABLEINDEX nIndex
, XACTVARIABLEVALUE nValue
)
274 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
276 TRACE("(%p)->(%u, %f)\n", iface
, nIndex
, nValue
);
278 return FACTCue_SetVariable(This
->fact_cue
, nIndex
, nValue
);
281 static HRESULT WINAPI
IXACT3CueImpl_GetVariable(IXACT3Cue
*iface
,
282 XACTVARIABLEINDEX nIndex
, XACTVARIABLEVALUE
*nValue
)
284 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
286 TRACE("(%p)->(%u, %p)\n", iface
, nIndex
, nValue
);
288 return FACTCue_GetVariable(This
->fact_cue
, nIndex
, nValue
);
291 static HRESULT WINAPI
IXACT3CueImpl_Pause(IXACT3Cue
*iface
, BOOL fPause
)
293 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
295 TRACE("(%p)->(%u)\n", iface
, fPause
);
297 return FACTCue_Pause(This
->fact_cue
, fPause
);
300 #if XACT3_VER >= 0x0205
301 static HRESULT WINAPI
IXACT3CueImpl_GetProperties(IXACT3Cue
*iface
,
302 XACT_CUE_INSTANCE_PROPERTIES
**ppProperties
)
304 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
305 FACTCueInstanceProperties
*fProps
;
308 TRACE("(%p)->(%p)\n", iface
, ppProperties
);
310 hr
= FACTCue_GetProperties(This
->fact_cue
, &fProps
);
314 *ppProperties
= (XACT_CUE_INSTANCE_PROPERTIES
*) fProps
;
319 #if XACT3_VER >= 0x0305
320 static HRESULT WINAPI
IXACT3CueImpl_SetOutputVoices(IXACT3Cue
*iface
,
321 const XAUDIO2_VOICE_SENDS
*pSendList
)
323 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
324 FIXME("(%p)->(%p): stub!\n", This
, pSendList
);
328 static HRESULT WINAPI
IXACT3CueImpl_SetOutputVoiceMatrix(IXACT3Cue
*iface
,
329 IXAudio2Voice
*pDestinationVoice
, UINT32 SourceChannels
,
330 UINT32 DestinationChannels
, const float *pLevelMatrix
)
332 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
333 FIXME("(%p)->(%p %u %u %p): stub!\n", This
, pDestinationVoice
, SourceChannels
,
334 DestinationChannels
, pLevelMatrix
);
339 static const IXACT3CueVtbl XACT3Cue_Vtbl
=
343 IXACT3CueImpl_GetState
,
344 IXACT3CueImpl_Destroy
,
345 #if XACT3_VER < 0x0300
346 IXACT3CueImpl_GetChannelMap
,
347 IXACT3CueImpl_SetChannelMap
,
348 IXACT3CueImpl_GetChannelVolume
,
349 IXACT3CueImpl_SetChannelVolume
,
351 IXACT3CueImpl_SetMatrixCoefficients
,
352 IXACT3CueImpl_GetVariableIndex
,
353 IXACT3CueImpl_SetVariable
,
354 IXACT3CueImpl_GetVariable
,
356 #if XACT3_VER >= 0x0205
357 IXACT3CueImpl_GetProperties
,
359 #if XACT3_VER >= 0x0305
360 IXACT3CueImpl_SetOutputVoices
,
361 IXACT3CueImpl_SetOutputVoiceMatrix
365 typedef struct _XACT3SoundBankImpl
{
366 IXACT3SoundBank IXACT3SoundBank_iface
;
368 FACTSoundBank
*fact_soundbank
;
369 XACT3EngineImpl
*engine
;
370 } XACT3SoundBankImpl
;
372 static inline XACT3SoundBankImpl
*impl_from_IXACT3SoundBank(IXACT3SoundBank
*iface
)
374 return CONTAINING_RECORD(iface
, XACT3SoundBankImpl
, IXACT3SoundBank_iface
);
377 static XACTINDEX WINAPI
IXACT3SoundBankImpl_GetCueIndex(IXACT3SoundBank
*iface
,
378 PCSTR szFriendlyName
)
380 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
382 TRACE("(%p)->(%s)\n", This
, szFriendlyName
);
384 return FACTSoundBank_GetCueIndex(This
->fact_soundbank
, szFriendlyName
);
387 #if XACT3_VER >= 0x0205
388 static HRESULT WINAPI
IXACT3SoundBankImpl_GetNumCues(IXACT3SoundBank
*iface
,
389 XACTINDEX
*pnNumCues
)
391 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
393 TRACE("(%p)->(%p)\n", This
, pnNumCues
);
395 return FACTSoundBank_GetNumCues(This
->fact_soundbank
, pnNumCues
);
398 static HRESULT WINAPI
IXACT3SoundBankImpl_GetCueProperties(IXACT3SoundBank
*iface
,
399 XACTINDEX nCueIndex
, XACT_CUE_PROPERTIES
*pProperties
)
401 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
403 TRACE("(%p)->(%u, %p)\n", This
, nCueIndex
, pProperties
);
405 return FACTSoundBank_GetCueProperties(This
->fact_soundbank
, nCueIndex
,
406 (FACTCueProperties
*) pProperties
);
410 static HRESULT WINAPI
IXACT3SoundBankImpl_Prepare(IXACT3SoundBank
*iface
,
411 XACTINDEX nCueIndex
, DWORD dwFlags
, XACTTIME timeOffset
,
414 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
420 TRACE("(%p)->(%u, 0x%lx, %lu, %p)\n", This
, nCueIndex
, dwFlags
, timeOffset
,
423 ret
= FACTSoundBank_Prepare(This
->fact_soundbank
, nCueIndex
, dwFlags
,
427 ERR("Failed to CreateCue: %d\n", ret
);
431 cue
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*cue
));
434 FACTCue_Destroy(fcue
);
435 ERR("Failed to allocate XACT3CueImpl!\n");
436 return E_OUTOFMEMORY
;
439 hr
= wrapper_add_entry(This
->engine
, fcue
, &cue
->IXACT3Cue_iface
);
442 FACTCue_Destroy(fcue
);
443 HeapFree(GetProcessHeap(), 0, cue
);
447 cue
->IXACT3Cue_iface
.lpVtbl
= &XACT3Cue_Vtbl
;
448 cue
->fact_cue
= fcue
;
449 cue
->engine
= This
->engine
;
450 *ppCue
= &cue
->IXACT3Cue_iface
;
452 TRACE("Created Cue: %p\n", cue
);
457 static HRESULT WINAPI
IXACT3SoundBankImpl_Play(IXACT3SoundBank
*iface
,
458 XACTINDEX nCueIndex
, DWORD dwFlags
, XACTTIME timeOffset
,
461 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
466 TRACE("(%p)->(%u, 0x%lx, %lu, %p)\n", This
, nCueIndex
, dwFlags
, timeOffset
,
469 /* If the application doesn't want a handle, don't generate one at all.
470 * Let the engine handle that memory instead.
474 hr
= FACTSoundBank_Play(This
->fact_soundbank
, nCueIndex
, dwFlags
,
477 hr
= FACTSoundBank_Play(This
->fact_soundbank
, nCueIndex
, dwFlags
,
482 cue
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*cue
));
485 FACTCue_Destroy(fcue
);
486 ERR("Failed to allocate XACT3CueImpl!\n");
487 return E_OUTOFMEMORY
;
490 hr
= wrapper_add_entry(This
->engine
, fcue
, &cue
->IXACT3Cue_iface
);
493 FACTCue_Destroy(fcue
);
494 HeapFree(GetProcessHeap(), 0, cue
);
498 cue
->IXACT3Cue_iface
.lpVtbl
= &XACT3Cue_Vtbl
;
499 cue
->fact_cue
= fcue
;
500 cue
->engine
= This
->engine
;
501 *ppCue
= &cue
->IXACT3Cue_iface
;
507 static HRESULT WINAPI
IXACT3SoundBankImpl_Stop(IXACT3SoundBank
*iface
,
508 XACTINDEX nCueIndex
, DWORD dwFlags
)
510 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
512 TRACE("(%p)->(%lu)\n", This
, dwFlags
);
514 return FACTSoundBank_Stop(This
->fact_soundbank
, nCueIndex
, dwFlags
);
517 static HRESULT WINAPI
IXACT3SoundBankImpl_Destroy(IXACT3SoundBank
*iface
)
519 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
522 TRACE("(%p)\n", This
);
524 hr
= FACTSoundBank_Destroy(This
->fact_soundbank
);
526 wrapper_remove_entry(This
->engine
, This
->fact_soundbank
);
527 HeapFree(GetProcessHeap(), 0, This
);
531 static HRESULT WINAPI
IXACT3SoundBankImpl_GetState(IXACT3SoundBank
*iface
,
534 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
536 TRACE("(%p)->(%p)\n", This
, pdwState
);
538 return FACTSoundBank_GetState(This
->fact_soundbank
, (uint32_t *)pdwState
);
541 static const IXACT3SoundBankVtbl XACT3SoundBank_Vtbl
=
543 IXACT3SoundBankImpl_GetCueIndex
,
544 #if XACT3_VER >= 0x0205
545 IXACT3SoundBankImpl_GetNumCues
,
546 IXACT3SoundBankImpl_GetCueProperties
,
548 IXACT3SoundBankImpl_Prepare
,
549 IXACT3SoundBankImpl_Play
,
550 IXACT3SoundBankImpl_Stop
,
551 IXACT3SoundBankImpl_Destroy
,
552 IXACT3SoundBankImpl_GetState
555 #if XACT3_VER >= 0x0205
557 typedef struct _XACT3WaveImpl
{
558 IXACT3Wave IXACT3Wave_iface
;
561 XACT3EngineImpl
*engine
;
564 static inline XACT3WaveImpl
*impl_from_IXACT3Wave(IXACT3Wave
*iface
)
566 return CONTAINING_RECORD(iface
, XACT3WaveImpl
, IXACT3Wave_iface
);
569 static HRESULT WINAPI
IXACT3WaveImpl_Destroy(IXACT3Wave
*iface
)
571 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
574 TRACE("(%p)\n", This
);
576 hr
= FACTWave_Destroy(This
->fact_wave
);
577 wrapper_remove_entry(This
->engine
, This
->fact_wave
);
578 HeapFree(GetProcessHeap(), 0, This
);
582 static HRESULT WINAPI
IXACT3WaveImpl_Play(IXACT3Wave
*iface
)
584 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
586 TRACE("(%p)\n", This
);
588 return FACTWave_Play(This
->fact_wave
);
591 static HRESULT WINAPI
IXACT3WaveImpl_Stop(IXACT3Wave
*iface
, DWORD dwFlags
)
593 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
595 TRACE("(%p)->(0x%lx)\n", This
, dwFlags
);
597 return FACTWave_Stop(This
->fact_wave
, dwFlags
);
600 static HRESULT WINAPI
IXACT3WaveImpl_Pause(IXACT3Wave
*iface
, BOOL fPause
)
602 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
604 TRACE("(%p)->(%u)\n", This
, fPause
);
606 return FACTWave_Pause(This
->fact_wave
, fPause
);
609 static HRESULT WINAPI
IXACT3WaveImpl_GetState(IXACT3Wave
*iface
, DWORD
*pdwState
)
611 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
613 TRACE("(%p)->(%p)\n", This
, pdwState
);
615 return FACTWave_GetState(This
->fact_wave
, (uint32_t *)pdwState
);
618 static HRESULT WINAPI
IXACT3WaveImpl_SetPitch(IXACT3Wave
*iface
, XACTPITCH pitch
)
620 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
622 TRACE("(%p)->(%d)\n", This
, pitch
);
624 return FACTWave_SetPitch(This
->fact_wave
, pitch
);
627 static HRESULT WINAPI
IXACT3WaveImpl_SetVolume(IXACT3Wave
*iface
, XACTVOLUME volume
)
629 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
631 TRACE("(%p)->(%f)\n", This
, volume
);
633 return FACTWave_SetVolume(This
->fact_wave
, volume
);
636 static HRESULT WINAPI
IXACT3WaveImpl_SetMatrixCoefficients(IXACT3Wave
*iface
,
637 UINT32 uSrcChannelCount
, UINT32 uDstChannelCount
,
638 float *pMatrixCoefficients
)
640 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
642 TRACE("(%p)->(%u, %u, %p)\n", This
, uSrcChannelCount
, uDstChannelCount
,
643 pMatrixCoefficients
);
645 return FACTWave_SetMatrixCoefficients(This
->fact_wave
, uSrcChannelCount
,
646 uDstChannelCount
, pMatrixCoefficients
);
649 static HRESULT WINAPI
IXACT3WaveImpl_GetProperties(IXACT3Wave
*iface
,
650 XACT_WAVE_INSTANCE_PROPERTIES
*pProperties
)
652 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
654 TRACE("(%p)->(%p)\n", This
, pProperties
);
656 return FACTWave_GetProperties(This
->fact_wave
,
657 (FACTWaveInstanceProperties
*) pProperties
);
660 static const IXACT3WaveVtbl XACT3Wave_Vtbl
=
662 IXACT3WaveImpl_Destroy
,
665 IXACT3WaveImpl_Pause
,
666 IXACT3WaveImpl_GetState
,
667 IXACT3WaveImpl_SetPitch
,
668 IXACT3WaveImpl_SetVolume
,
669 IXACT3WaveImpl_SetMatrixCoefficients
,
670 IXACT3WaveImpl_GetProperties
675 typedef struct _XACT3WaveBankImpl
{
676 IXACT3WaveBank IXACT3WaveBank_iface
;
678 FACTWaveBank
*fact_wavebank
;
679 struct _XACT3EngineImpl
*engine
;
682 static inline XACT3WaveBankImpl
*impl_from_IXACT3WaveBank(IXACT3WaveBank
*iface
)
684 return CONTAINING_RECORD(iface
, XACT3WaveBankImpl
, IXACT3WaveBank_iface
);
687 static HRESULT WINAPI
IXACT3WaveBankImpl_Destroy(IXACT3WaveBank
*iface
)
689 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
692 TRACE("(%p)\n", This
);
694 hr
= FACTWaveBank_Destroy(This
->fact_wavebank
);
696 wrapper_remove_entry(This
->engine
, This
->fact_wavebank
);
698 HeapFree(GetProcessHeap(), 0, This
);
702 #if XACT3_VER >= 0x0205
704 static HRESULT WINAPI
IXACT3WaveBankImpl_GetNumWaves(IXACT3WaveBank
*iface
,
705 XACTINDEX
*pnNumWaves
)
707 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
709 TRACE("(%p)->(%p)\n", This
, pnNumWaves
);
711 return FACTWaveBank_GetNumWaves(This
->fact_wavebank
, pnNumWaves
);
714 static XACTINDEX WINAPI
IXACT3WaveBankImpl_GetWaveIndex(IXACT3WaveBank
*iface
,
715 PCSTR szFriendlyName
)
717 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
719 TRACE("(%p)->(%s)\n", This
, szFriendlyName
);
721 return FACTWaveBank_GetWaveIndex(This
->fact_wavebank
, szFriendlyName
);
724 static HRESULT WINAPI
IXACT3WaveBankImpl_GetWaveProperties(IXACT3WaveBank
*iface
,
725 XACTINDEX nWaveIndex
, XACT_WAVE_PROPERTIES
*pWaveProperties
)
727 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
729 TRACE("(%p)->(%u, %p)\n", This
, nWaveIndex
, pWaveProperties
);
731 return FACTWaveBank_GetWaveProperties(This
->fact_wavebank
, nWaveIndex
,
732 (FACTWaveProperties
*) pWaveProperties
);
735 static HRESULT WINAPI
IXACT3WaveBankImpl_Prepare(IXACT3WaveBank
*iface
,
736 XACTINDEX nWaveIndex
, DWORD dwFlags
, DWORD dwPlayOffset
,
737 XACTLOOPCOUNT nLoopCount
, IXACT3Wave
** ppWave
)
739 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
745 TRACE("(%p)->(0x%x, %lu, 0x%lx, %u, %p)\n", This
, nWaveIndex
, dwFlags
,
746 dwPlayOffset
, nLoopCount
, ppWave
);
748 ret
= FACTWaveBank_Prepare(This
->fact_wavebank
, nWaveIndex
, dwFlags
,
749 dwPlayOffset
, nLoopCount
, &fwave
);
752 ERR("Failed to CreateWave: %d\n", ret
);
756 wave
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*wave
));
759 FACTWave_Destroy(fwave
);
760 ERR("Failed to allocate XACT3WaveImpl!\n");
761 return E_OUTOFMEMORY
;
764 hr
= wrapper_add_entry(This
->engine
, fwave
, &wave
->IXACT3Wave_iface
);
767 FACTWave_Destroy(fwave
);
768 HeapFree(GetProcessHeap(), 0, wave
);
772 wave
->IXACT3Wave_iface
.lpVtbl
= &XACT3Wave_Vtbl
;
773 wave
->fact_wave
= fwave
;
774 wave
->engine
= This
->engine
;
775 *ppWave
= &wave
->IXACT3Wave_iface
;
777 TRACE("Created Wave: %p\n", wave
);
782 static HRESULT WINAPI
IXACT3WaveBankImpl_Play(IXACT3WaveBank
*iface
,
783 XACTINDEX nWaveIndex
, DWORD dwFlags
, DWORD dwPlayOffset
,
784 XACTLOOPCOUNT nLoopCount
, IXACT3Wave
** ppWave
)
786 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
791 TRACE("(%p)->(0x%x, %lu, 0x%lx, %u, %p)\n", This
, nWaveIndex
, dwFlags
, dwPlayOffset
,
794 /* If the application doesn't want a handle, don't generate one at all.
795 * Let the engine handle that memory instead.
799 hr
= FACTWaveBank_Play(This
->fact_wavebank
, nWaveIndex
, dwFlags
,
800 dwPlayOffset
, nLoopCount
, NULL
);
802 hr
= FACTWaveBank_Play(This
->fact_wavebank
, nWaveIndex
, dwFlags
,
803 dwPlayOffset
, nLoopCount
, &fwave
);
807 wave
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*wave
));
810 FACTWave_Destroy(fwave
);
811 ERR("Failed to allocate XACT3WaveImpl!\n");
812 return E_OUTOFMEMORY
;
815 hr
= wrapper_add_entry(This
->engine
, fwave
, &wave
->IXACT3Wave_iface
);
818 FACTWave_Destroy(fwave
);
819 HeapFree(GetProcessHeap(), 0, wave
);
823 wave
->IXACT3Wave_iface
.lpVtbl
= &XACT3Wave_Vtbl
;
824 wave
->fact_wave
= fwave
;
825 wave
->engine
= This
->engine
;
826 *ppWave
= &wave
->IXACT3Wave_iface
;
832 static HRESULT WINAPI
IXACT3WaveBankImpl_Stop(IXACT3WaveBank
*iface
,
833 XACTINDEX nWaveIndex
, DWORD dwFlags
)
835 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
837 TRACE("(%p)->(%u, %lu)\n", This
, nWaveIndex
, dwFlags
);
839 return FACTWaveBank_Stop(This
->fact_wavebank
, nWaveIndex
, dwFlags
);
844 static HRESULT WINAPI
IXACT3WaveBankImpl_GetState(IXACT3WaveBank
*iface
,
847 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
849 TRACE("(%p)->(%p)\n", This
, pdwState
);
851 return FACTWaveBank_GetState(This
->fact_wavebank
, (uint32_t *)pdwState
);
854 static const IXACT3WaveBankVtbl XACT3WaveBank_Vtbl
=
856 IXACT3WaveBankImpl_Destroy
,
857 #if XACT3_VER >= 0x0205
858 IXACT3WaveBankImpl_GetNumWaves
,
859 IXACT3WaveBankImpl_GetWaveIndex
,
860 IXACT3WaveBankImpl_GetWaveProperties
,
861 IXACT3WaveBankImpl_Prepare
,
862 IXACT3WaveBankImpl_Play
,
863 IXACT3WaveBankImpl_Stop
,
865 IXACT3WaveBankImpl_GetState
868 typedef struct wrap_readfile_struct
{
869 XACT3EngineImpl
*engine
;
871 } wrap_readfile_struct
;
873 static int32_t FACTCALL
wrap_readfile(
876 uint32_t nNumberOfBytesRead
,
877 uint32_t *lpNumberOfBytesRead
,
878 FACTOverlapped
*lpOverlapped
)
880 wrap_readfile_struct
*wrap
= (wrap_readfile_struct
*) hFile
;
881 return wrap
->engine
->pReadFile(wrap
->file
, lpBuffer
, nNumberOfBytesRead
,
882 (DWORD
*)lpNumberOfBytesRead
, (LPOVERLAPPED
)lpOverlapped
);
885 static int32_t FACTCALL
wrap_getoverlappedresult(
887 FACTOverlapped
*lpOverlapped
,
888 uint32_t *lpNumberOfBytesTransferred
,
891 wrap_readfile_struct
*wrap
= (wrap_readfile_struct
*) hFile
;
892 return wrap
->engine
->pGetOverlappedResult(wrap
->file
, (LPOVERLAPPED
)lpOverlapped
,
893 (DWORD
*)lpNumberOfBytesTransferred
, bWait
);
896 static inline XACT3EngineImpl
*impl_from_IXACT3Engine(IXACT3Engine
*iface
)
898 return CONTAINING_RECORD(iface
, XACT3EngineImpl
, IXACT3Engine_iface
);
901 static HRESULT WINAPI
IXACT3EngineImpl_QueryInterface(IXACT3Engine
*iface
,
902 REFIID riid
, void **ppvObject
)
904 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
906 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
908 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
909 IsEqualGUID(riid
, &IID_IXACT3Engine
)){
910 *ppvObject
= &This
->IXACT3Engine_iface
;
916 IUnknown_AddRef((IUnknown
*)*ppvObject
);
920 FIXME("(%p)->(%s,%p), not found\n", This
, debugstr_guid(riid
), ppvObject
);
922 return E_NOINTERFACE
;
925 static ULONG WINAPI
IXACT3EngineImpl_AddRef(IXACT3Engine
*iface
)
927 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
928 ULONG ref
= FACTAudioEngine_AddRef(This
->fact_engine
);
929 TRACE("(%p)->(): Refcount now %lu\n", This
, ref
);
933 static ULONG WINAPI
IXACT3EngineImpl_Release(IXACT3Engine
*iface
)
935 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
936 ULONG ref
= FACTAudioEngine_Release(This
->fact_engine
);
938 TRACE("(%p)->(): Refcount now %lu\n", This
, ref
);
942 DeleteCriticalSection(&This
->wrapper_lookup_cs
);
943 wine_rb_destroy(&This
->wrapper_lookup
, wrapper_lookup_destroy
, NULL
);
944 HeapFree(GetProcessHeap(), 0, This
);
949 static HRESULT WINAPI
IXACT3EngineImpl_GetRendererCount(IXACT3Engine
*iface
,
950 XACTINDEX
*pnRendererCount
)
952 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
954 TRACE("(%p)->(%p)\n", This
, pnRendererCount
);
956 return FACTAudioEngine_GetRendererCount(This
->fact_engine
, pnRendererCount
);
959 static HRESULT WINAPI
IXACT3EngineImpl_GetRendererDetails(IXACT3Engine
*iface
,
960 XACTINDEX nRendererIndex
, XACT_RENDERER_DETAILS
*pRendererDetails
)
962 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
964 TRACE("(%p)->(%d, %p)\n", This
, nRendererIndex
, pRendererDetails
);
966 return FACTAudioEngine_GetRendererDetails(This
->fact_engine
,
967 nRendererIndex
, (FACTRendererDetails
*) pRendererDetails
);
970 #if XACT3_VER >= 0x0205
972 static HRESULT WINAPI
IXACT3EngineImpl_GetFinalMixFormat(IXACT3Engine
*iface
,
973 WAVEFORMATEXTENSIBLE
*pFinalMixFormat
)
975 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
977 TRACE("(%p)->(%p)\n", This
, pFinalMixFormat
);
979 return FACTAudioEngine_GetFinalMixFormat(This
->fact_engine
,
980 (FAudioWaveFormatExtensible
*) pFinalMixFormat
);
985 static XACTNOTIFICATIONTYPE
xact_notification_type_from_fact(uint8_t type
)
987 /* we can't use a switch statement, because the constants are static const
988 * variables, and some compilers can't deal with that */
989 #define X(a) if (type == FACTNOTIFICATIONTYPE_##a) return XACTNOTIFICATIONTYPE_##a
995 X(SOUNDBANKDESTROYED
);
996 X(WAVEBANKDESTROYED
);
997 X(LOCALVARIABLECHANGED
);
998 X(GLOBALVARIABLECHANGED
);
1003 X(WAVEBANKPREPARED
);
1004 X(WAVEBANKSTREAMING_INVALIDCONTENT
);
1005 #if XACT3_VER >= 0x0205
1012 FIXME("unknown type %#x\n", type
);
1016 static void FACTCALL
fact_notification_cb(const FACTNotification
*notification
)
1018 XACT3EngineImpl
*engine
= (XACT3EngineImpl
*)notification
->pvContext
;
1019 XACT_NOTIFICATION xnotification
;
1021 TRACE("notification %d, context %p\n", notification
->type
, notification
->pvContext
);
1023 /* Older versions of FAudio don't pass through the context */
1026 WARN("Notification context is NULL\n");
1030 xnotification
.type
= xact_notification_type_from_fact(notification
->type
);
1031 xnotification
.timeStamp
= notification
->timeStamp
;
1032 xnotification
.pvContext
= engine
->contexts
[notification
->type
];
1034 EnterCriticalSection(&engine
->wrapper_lookup_cs
);
1035 if (notification
->type
== XACTNOTIFICATIONTYPE_WAVEBANKPREPARED
1036 || notification
->type
== XACTNOTIFICATIONTYPE_WAVEBANKDESTROYED
)
1038 xnotification
.waveBank
.pWaveBank
= wrapper_find_entry(engine
, notification
->waveBank
.pWaveBank
);
1040 else if(notification
->type
== XACTNOTIFICATIONTYPE_SOUNDBANKDESTROYED
)
1042 xnotification
.soundBank
.pSoundBank
= wrapper_find_entry(engine
, notification
->soundBank
.pSoundBank
);
1044 else if (notification
->type
== XACTNOTIFICATIONTYPE_WAVESTOP
1045 #if XACT3_VER >= 0x0205
1046 || notification
->type
== XACTNOTIFICATIONTYPE_WAVEDESTROYED
1047 || notification
->type
== XACTNOTIFICATIONTYPE_WAVELOOPED
1048 || notification
->type
== XACTNOTIFICATIONTYPE_WAVEPLAY
1049 || notification
->type
== XACTNOTIFICATIONTYPE_WAVEPREPARED
)
1054 xnotification
.wave
.cueIndex
= notification
->wave
.cueIndex
;
1055 xnotification
.wave
.pCue
= wrapper_find_entry(engine
, notification
->wave
.pCue
);
1056 xnotification
.wave
.pSoundBank
= wrapper_find_entry(engine
, notification
->wave
.pSoundBank
);
1057 #if XACT3_VER >= 0x0205
1058 xnotification
.wave
.pWave
= wrapper_find_entry(engine
, notification
->wave
.pWave
);
1060 xnotification
.wave
.pWaveBank
= wrapper_find_entry(engine
, notification
->wave
.pWaveBank
);
1062 else if (notification
->type
== XACTNOTIFICATIONTYPE_CUEPLAY
||
1063 notification
->type
== XACTNOTIFICATIONTYPE_CUEPREPARED
||
1064 notification
->type
== XACTNOTIFICATIONTYPE_CUESTOP
||
1065 notification
->type
== XACTNOTIFICATIONTYPE_CUEDESTROYED
)
1067 xnotification
.cue
.pCue
= wrapper_find_entry(engine
, notification
->cue
.pCue
);
1068 xnotification
.cue
.cueIndex
= notification
->cue
.cueIndex
;
1069 xnotification
.cue
.pSoundBank
= wrapper_find_entry(engine
, notification
->cue
.pSoundBank
);
1073 LeaveCriticalSection(&engine
->wrapper_lookup_cs
);
1074 FIXME("Unsupported callback type %d\n", notification
->type
);
1077 LeaveCriticalSection(&engine
->wrapper_lookup_cs
);
1079 engine
->notification_callback(&xnotification
);
1082 static HRESULT WINAPI
IXACT3EngineImpl_Initialize(IXACT3Engine
*iface
,
1083 const XACT_RUNTIME_PARAMETERS
*pParams
)
1085 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1086 FACTRuntimeParameters params
;
1089 TRACE("(%p)->(%p)\n", This
, pParams
);
1091 memset(¶ms
, 0, sizeof(FACTRuntimeParameters
));
1092 /* Explicitly copy to the FAudio structure as the packing is wrong under 64 bits */
1093 params
.lookAheadTime
= pParams
->lookAheadTime
;
1094 params
.pGlobalSettingsBuffer
= pParams
->pGlobalSettingsBuffer
;
1095 params
.globalSettingsBufferSize
= pParams
->globalSettingsBufferSize
;
1096 params
.globalSettingsFlags
= pParams
->globalSettingsFlags
;
1097 params
.globalSettingsAllocAttributes
= pParams
->globalSettingsAllocAttributes
;
1098 params
.pRendererID
= (int16_t*)pParams
->pRendererID
;
1099 params
.pXAudio2
= NULL
;
1100 params
.pMasteringVoice
= NULL
;
1102 #if XACT3_VER >= 0x0300
1103 /* FIXME: pXAudio2 and pMasteringVoice are pointers to
1104 * IXAudio2/IXAudio2MasteringVoice objects. FACT wants pointers to
1105 * FAudio/FAudioMasteringVoice objects. In Wine's XAudio2 implementation, we
1106 * actually have them available, but only if you access their internal data.
1107 * For now we can just force these pointers to NULL, as XACT simply
1108 * generates its own engine and endpoint in that situation. These parameters
1109 * are mostly an optimization for games with multiple XACT3Engines that want
1110 * a single engine running everything.
1113 if (pParams
->pXAudio2
!= NULL
){
1114 FIXME("pXAudio2 parameter not supported!\n");
1116 if (pParams
->pMasteringVoice
!= NULL
){
1117 FIXME("pMasteringVoice parameter not supported!\n");
1122 /* Force Windows I/O, do NOT use the FACT default! */
1123 This
->pReadFile
= (XACT_READFILE_CALLBACK
)
1124 pParams
->fileIOCallbacks
.readFileCallback
;
1125 This
->pGetOverlappedResult
= (XACT_GETOVERLAPPEDRESULT_CALLBACK
)
1126 pParams
->fileIOCallbacks
.getOverlappedResultCallback
;
1127 if (This
->pReadFile
== NULL
)
1128 This
->pReadFile
= (XACT_READFILE_CALLBACK
) ReadFile
;
1129 if (This
->pGetOverlappedResult
== NULL
)
1130 This
->pGetOverlappedResult
= (XACT_GETOVERLAPPEDRESULT_CALLBACK
)
1131 GetOverlappedResult
;
1132 params
.fileIOCallbacks
.readFileCallback
= wrap_readfile
;
1133 params
.fileIOCallbacks
.getOverlappedResultCallback
= wrap_getoverlappedresult
;
1134 params
.fnNotificationCallback
= fact_notification_cb
;
1136 This
->notification_callback
= (XACT_NOTIFICATION_CALLBACK
)pParams
->fnNotificationCallback
;
1138 ret
= FACTAudioEngine_Initialize(This
->fact_engine
, ¶ms
);
1140 WARN("FACTAudioEngine_Initialize returned %d\n", ret
);
1142 return !ret
? S_OK
: E_FAIL
;
1145 static HRESULT WINAPI
IXACT3EngineImpl_ShutDown(IXACT3Engine
*iface
)
1147 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1149 TRACE("(%p)\n", This
);
1151 return FACTAudioEngine_ShutDown(This
->fact_engine
);
1154 static HRESULT WINAPI
IXACT3EngineImpl_DoWork(IXACT3Engine
*iface
)
1156 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1158 TRACE("(%p)\n", This
);
1160 return FACTAudioEngine_DoWork(This
->fact_engine
);
1163 static HRESULT WINAPI
IXACT3EngineImpl_CreateSoundBank(IXACT3Engine
*iface
,
1164 const void* pvBuffer
, DWORD dwSize
, DWORD dwFlags
,
1165 DWORD dwAllocAttributes
, IXACT3SoundBank
**ppSoundBank
)
1167 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1168 XACT3SoundBankImpl
*sb
;
1173 TRACE("(%p)->(%p, %lu, 0x%lx, 0x%lx, %p): stub!\n", This
, pvBuffer
, dwSize
, dwFlags
,
1174 dwAllocAttributes
, ppSoundBank
);
1176 ret
= FACTAudioEngine_CreateSoundBank(This
->fact_engine
, pvBuffer
, dwSize
,
1177 dwFlags
, dwAllocAttributes
, &fsb
);
1180 ERR("Failed to CreateSoundBank: %d\n", ret
);
1184 sb
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*sb
));
1187 FACTSoundBank_Destroy(fsb
);
1188 ERR("Failed to allocate XACT3SoundBankImpl!\n");
1189 return E_OUTOFMEMORY
;
1192 hr
= wrapper_add_entry(This
, fsb
, &sb
->IXACT3SoundBank_iface
);
1195 FACTSoundBank_Destroy(fsb
);
1196 HeapFree(GetProcessHeap(), 0, sb
);
1200 sb
->IXACT3SoundBank_iface
.lpVtbl
= &XACT3SoundBank_Vtbl
;
1201 sb
->fact_soundbank
= fsb
;
1203 *ppSoundBank
= &sb
->IXACT3SoundBank_iface
;
1205 TRACE("Created SoundBank: %p\n", sb
);
1210 static HRESULT WINAPI
IXACT3EngineImpl_CreateInMemoryWaveBank(IXACT3Engine
*iface
,
1211 const void* pvBuffer
, DWORD dwSize
, DWORD dwFlags
,
1212 DWORD dwAllocAttributes
, IXACT3WaveBank
**ppWaveBank
)
1214 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1215 XACT3WaveBankImpl
*wb
;
1220 TRACE("(%p)->(%p, %lu, 0x%lx, 0x%lx, %p)\n", This
, pvBuffer
, dwSize
, dwFlags
,
1221 dwAllocAttributes
, ppWaveBank
);
1223 ret
= FACTAudioEngine_CreateInMemoryWaveBank(This
->fact_engine
, pvBuffer
,
1224 dwSize
, dwFlags
, dwAllocAttributes
, &fwb
);
1227 ERR("Failed to CreateWaveBank: %d\n", ret
);
1231 wb
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*wb
));
1234 FACTWaveBank_Destroy(fwb
);
1235 ERR("Failed to allocate XACT3WaveBankImpl!\n");
1236 return E_OUTOFMEMORY
;
1239 hr
= wrapper_add_entry(This
, fwb
, &wb
->IXACT3WaveBank_iface
);
1242 FACTWaveBank_Destroy(fwb
);
1243 HeapFree(GetProcessHeap(), 0, wb
);
1247 wb
->IXACT3WaveBank_iface
.lpVtbl
= &XACT3WaveBank_Vtbl
;
1248 wb
->fact_wavebank
= fwb
;
1250 *ppWaveBank
= &wb
->IXACT3WaveBank_iface
;
1252 TRACE("Created in-memory WaveBank: %p\n", wb
);
1257 static HRESULT WINAPI
IXACT3EngineImpl_CreateStreamingWaveBank(IXACT3Engine
*iface
,
1258 const XACT_WAVEBANK_STREAMING_PARAMETERS
*pParms
,
1259 IXACT3WaveBank
**ppWaveBank
)
1261 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1262 FACTStreamingParameters fakeParms
;
1263 wrap_readfile_struct
*fake
;
1264 XACT3WaveBankImpl
*wb
;
1269 TRACE("(%p)->(%p, %p)\n", This
, pParms
, ppWaveBank
);
1271 /* We have to wrap the file to fix up the callbacks! */
1272 fake
= (wrap_readfile_struct
*) CoTaskMemAlloc(
1273 sizeof(wrap_readfile_struct
));
1274 fake
->engine
= This
;
1275 fake
->file
= pParms
->file
;
1276 fakeParms
.file
= fake
;
1277 fakeParms
.flags
= pParms
->flags
;
1278 fakeParms
.offset
= pParms
->offset
;
1279 fakeParms
.packetSize
= pParms
->packetSize
;
1281 ret
= FACTAudioEngine_CreateStreamingWaveBank(This
->fact_engine
, &fakeParms
,
1285 ERR("Failed to CreateWaveBank: %d\n", ret
);
1289 wb
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*wb
));
1292 FACTWaveBank_Destroy(fwb
);
1293 ERR("Failed to allocate XACT3WaveBankImpl!\n");
1294 return E_OUTOFMEMORY
;
1297 hr
= wrapper_add_entry(This
, fwb
, &wb
->IXACT3WaveBank_iface
);
1300 FACTWaveBank_Destroy(fwb
);
1301 HeapFree(GetProcessHeap(), 0, wb
);
1305 wb
->IXACT3WaveBank_iface
.lpVtbl
= &XACT3WaveBank_Vtbl
;
1306 wb
->fact_wavebank
= fwb
;
1308 *ppWaveBank
= &wb
->IXACT3WaveBank_iface
;
1310 TRACE("Created streaming WaveBank: %p\n", wb
);
1315 #if XACT3_VER >= 0x0205
1317 static HRESULT WINAPI
IXACT3EngineImpl_PrepareInMemoryWave(IXACT3Engine
*iface
,
1318 DWORD dwFlags
, WAVEBANKENTRY entry
, DWORD
*pdwSeekTable
,
1319 BYTE
*pbWaveData
, DWORD dwPlayOffset
, XACTLOOPCOUNT nLoopCount
,
1320 IXACT3Wave
**ppWave
)
1322 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1323 FIXME("(%p): stub!\n", This
);
1327 static HRESULT WINAPI
IXACT3EngineImpl_PrepareStreamingWave(IXACT3Engine
*iface
,
1328 DWORD dwFlags
, WAVEBANKENTRY entry
,
1329 XACT_STREAMING_PARAMETERS streamingParams
, DWORD dwAlignment
,
1330 DWORD
*pdwSeekTable
, DWORD dwPlayOffset
, XACTLOOPCOUNT nLoopCount
,
1331 IXACT3Wave
**ppWave
)
1333 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1334 FIXME("(%p): stub!\n", This
);
1338 static HRESULT WINAPI
IXACT3EngineImpl_PrepareWave(IXACT3Engine
*iface
,
1339 DWORD dwFlags
, PCSTR szWavePath
, WORD wStreamingPacketSize
,
1340 DWORD dwAlignment
, DWORD dwPlayOffset
, XACTLOOPCOUNT nLoopCount
,
1341 IXACT3Wave
**ppWave
)
1343 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1344 XACT3WaveImpl
*wave
;
1345 FACTWave
*fwave
= NULL
;
1349 TRACE("(%p)->(0x%08lx, %s, %d, %ld, %ld, %d, %p)\n", This
, dwFlags
, debugstr_a(szWavePath
),
1350 wStreamingPacketSize
, dwAlignment
, dwPlayOffset
, nLoopCount
, ppWave
);
1352 ret
= FACTAudioEngine_PrepareWave(This
->fact_engine
, dwFlags
, szWavePath
, wStreamingPacketSize
,
1353 dwAlignment
, dwPlayOffset
, nLoopCount
, &fwave
);
1354 if(ret
!= 0 || !fwave
)
1356 ERR("Failed to CreateWave: %d (%p)\n", ret
, fwave
);
1360 wave
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*wave
));
1363 FACTWave_Destroy(fwave
);
1364 return E_OUTOFMEMORY
;
1367 hr
= wrapper_add_entry(This
, fwave
, &wave
->IXACT3Wave_iface
);
1370 FACTWave_Destroy(fwave
);
1371 HeapFree(GetProcessHeap(), 0, wave
);
1375 wave
->IXACT3Wave_iface
.lpVtbl
= &XACT3Wave_Vtbl
;
1376 wave
->fact_wave
= fwave
;
1377 wave
->engine
= This
;
1378 *ppWave
= &wave
->IXACT3Wave_iface
;
1380 TRACE("Created Wave: %p\n", wave
);
1388 NOTIFY_SoundBank
= 0x01,
1389 NOTIFY_WaveBank
= 0x02,
1392 NOTIFY_cueIndex
= 0x10,
1393 NOTIFY_waveIndex
= 0x20
1396 /* these constants don't have the same values across xactengine versions */
1397 static uint8_t fact_notification_type_from_xact(XACTNOTIFICATIONTYPE type
)
1399 /* we can't use a switch statement, because the constants are static const
1400 * variables, and some compilers can't deal with that */
1401 #define X(a) if (type == XACTNOTIFICATIONTYPE_##a) return FACTNOTIFICATIONTYPE_##a
1407 X(SOUNDBANKDESTROYED
);
1408 X(WAVEBANKDESTROYED
);
1409 X(LOCALVARIABLECHANGED
);
1410 X(GLOBALVARIABLECHANGED
);
1415 X(WAVEBANKPREPARED
);
1416 X(WAVEBANKSTREAMING_INVALIDCONTENT
);
1417 #if XACT3_VER >= 0x0205
1424 FIXME("unknown type %#x\n", type
);
1428 static inline void unwrap_notificationdesc(FACTNotificationDescription
*fd
,
1429 const XACT_NOTIFICATION_DESCRIPTION
*xd
)
1433 TRACE("Type %d\n", xd
->type
);
1435 memset(fd
, 0, sizeof(*fd
));
1437 fd
->type
= fact_notification_type_from_xact(xd
->type
);
1439 /* we can't use a switch statement, because the constants are static const
1440 * variables, and some compilers can't deal with that */
1442 /* Supports SoundBank, Cue index, Cue instance */
1443 if (fd
->type
== FACTNOTIFICATIONTYPE_CUEPREPARED
|| fd
->type
== FACTNOTIFICATIONTYPE_CUEPLAY
||
1444 fd
->type
== FACTNOTIFICATIONTYPE_CUESTOP
|| fd
->type
== FACTNOTIFICATIONTYPE_CUEDESTROYED
||
1445 fd
->type
== FACTNOTIFICATIONTYPE_MARKER
|| fd
->type
== FACTNOTIFICATIONTYPE_LOCALVARIABLECHANGED
)
1447 flags
= NOTIFY_SoundBank
| NOTIFY_cueIndex
| NOTIFY_Cue
;
1449 /* Supports WaveBank */
1450 else if (fd
->type
== FACTNOTIFICATIONTYPE_WAVEBANKDESTROYED
|| fd
->type
== FACTNOTIFICATIONTYPE_WAVEBANKPREPARED
||
1451 fd
->type
== FACTNOTIFICATIONTYPE_WAVEBANKSTREAMING_INVALIDCONTENT
)
1453 flags
= NOTIFY_WaveBank
;
1455 /* Supports NOTIFY_SoundBank */
1456 else if (fd
->type
== FACTNOTIFICATIONTYPE_SOUNDBANKDESTROYED
)
1458 flags
= NOTIFY_SoundBank
;
1460 /* Supports SoundBank, SoundBank, Cue index, Cue instance, WaveBank, Wave instance */
1461 else if (fd
->type
== FACTNOTIFICATIONTYPE_WAVEPLAY
|| fd
->type
== FACTNOTIFICATIONTYPE_WAVESTOP
||
1462 fd
->type
== FACTNOTIFICATIONTYPE_WAVELOOPED
)
1464 flags
= NOTIFY_SoundBank
| NOTIFY_cueIndex
| NOTIFY_Cue
| NOTIFY_WaveBank
| NOTIFY_Wave
;
1466 /* Supports WaveBank, Wave index, Wave instance */
1467 else if (fd
->type
== FACTNOTIFICATIONTYPE_WAVEPREPARED
|| fd
->type
== FACTNOTIFICATIONTYPE_WAVEDESTROYED
)
1469 flags
= NOTIFY_WaveBank
| NOTIFY_waveIndex
| NOTIFY_Wave
;
1472 /* We have to unwrap the FACT object first! */
1473 fd
->flags
= xd
->flags
;
1474 if (flags
& NOTIFY_cueIndex
)
1475 fd
->cueIndex
= xd
->cueIndex
;
1476 #if XACT3_VER >= 0x0205
1477 if (flags
& NOTIFY_waveIndex
)
1478 fd
->waveIndex
= xd
->waveIndex
;
1481 if (flags
& NOTIFY_Cue
&& xd
->pCue
!= NULL
)
1483 XACT3CueImpl
*cue
= impl_from_IXACT3Cue(xd
->pCue
);
1485 fd
->pCue
= cue
->fact_cue
;
1488 if (flags
& NOTIFY_SoundBank
&& xd
->pSoundBank
!= NULL
)
1490 XACT3SoundBankImpl
*sound
= impl_from_IXACT3SoundBank(xd
->pSoundBank
);
1492 fd
->pSoundBank
= sound
->fact_soundbank
;
1495 if (flags
& NOTIFY_WaveBank
&& xd
->pWaveBank
!= NULL
)
1497 XACT3WaveBankImpl
*bank
= impl_from_IXACT3WaveBank(xd
->pWaveBank
);
1499 fd
->pWaveBank
= bank
->fact_wavebank
;
1502 #if XACT3_VER >= 0x0205
1503 if (flags
& NOTIFY_Wave
&& xd
->pWave
!= NULL
)
1505 XACT3WaveImpl
*wave
= impl_from_IXACT3Wave(xd
->pWave
);
1507 fd
->pWave
= wave
->fact_wave
;
1512 static HRESULT WINAPI
IXACT3EngineImpl_RegisterNotification(IXACT3Engine
*iface
,
1513 const XACT_NOTIFICATION_DESCRIPTION
*pNotificationDesc
)
1515 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1516 FACTNotificationDescription fdesc
;
1518 TRACE("(%p)->(%p)\n", This
, pNotificationDesc
);
1520 if (pNotificationDesc
->type
< XACTNOTIFICATIONTYPE_CUEPREPARED
||
1521 pNotificationDesc
->type
> XACTNOTIFICATIONTYPE_WAVEBANKSTREAMING_INVALIDCONTENT
)
1522 return E_INVALIDARG
;
1524 unwrap_notificationdesc(&fdesc
, pNotificationDesc
);
1525 This
->contexts
[pNotificationDesc
->type
] = pNotificationDesc
->pvContext
;
1526 fdesc
.pvContext
= This
;
1527 return FACTAudioEngine_RegisterNotification(This
->fact_engine
, &fdesc
);
1530 static HRESULT WINAPI
IXACT3EngineImpl_UnRegisterNotification(IXACT3Engine
*iface
,
1531 const XACT_NOTIFICATION_DESCRIPTION
*pNotificationDesc
)
1533 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1534 FACTNotificationDescription fdesc
;
1536 TRACE("(%p)->(%p)\n", This
, pNotificationDesc
);
1538 if (pNotificationDesc
->type
< XACTNOTIFICATIONTYPE_CUEPREPARED
||
1539 pNotificationDesc
->type
> XACTNOTIFICATIONTYPE_WAVEBANKSTREAMING_INVALIDCONTENT
)
1542 unwrap_notificationdesc(&fdesc
, pNotificationDesc
);
1543 fdesc
.pvContext
= This
;
1544 return FACTAudioEngine_UnRegisterNotification(This
->fact_engine
, &fdesc
);
1547 static XACTCATEGORY WINAPI
IXACT3EngineImpl_GetCategory(IXACT3Engine
*iface
,
1548 PCSTR szFriendlyName
)
1550 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1552 TRACE("(%p)->(%s)\n", This
, szFriendlyName
);
1554 return FACTAudioEngine_GetCategory(This
->fact_engine
, szFriendlyName
);
1557 static HRESULT WINAPI
IXACT3EngineImpl_Stop(IXACT3Engine
*iface
,
1558 XACTCATEGORY nCategory
, DWORD dwFlags
)
1560 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1562 TRACE("(%p)->(%u, 0x%lx)\n", This
, nCategory
, dwFlags
);
1564 return FACTAudioEngine_Stop(This
->fact_engine
, nCategory
, dwFlags
);
1567 static HRESULT WINAPI
IXACT3EngineImpl_SetVolume(IXACT3Engine
*iface
,
1568 XACTCATEGORY nCategory
, XACTVOLUME nVolume
)
1570 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1572 TRACE("(%p)->(%u, %f)\n", This
, nCategory
, nVolume
);
1574 return FACTAudioEngine_SetVolume(This
->fact_engine
, nCategory
, nVolume
);
1577 static HRESULT WINAPI
IXACT3EngineImpl_Pause(IXACT3Engine
*iface
,
1578 XACTCATEGORY nCategory
, BOOL fPause
)
1580 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1582 TRACE("(%p)->(%u, %u)\n", This
, nCategory
, fPause
);
1584 return FACTAudioEngine_Pause(This
->fact_engine
, nCategory
, fPause
);
1587 static XACTVARIABLEINDEX WINAPI
IXACT3EngineImpl_GetGlobalVariableIndex(
1588 IXACT3Engine
*iface
, PCSTR szFriendlyName
)
1590 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1592 TRACE("(%p)->(%s)\n", This
, szFriendlyName
);
1594 return FACTAudioEngine_GetGlobalVariableIndex(This
->fact_engine
,
1598 static HRESULT WINAPI
IXACT3EngineImpl_SetGlobalVariable(IXACT3Engine
*iface
,
1599 XACTVARIABLEINDEX nIndex
, XACTVARIABLEVALUE nValue
)
1601 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1603 TRACE("(%p)->(%u, %f)\n", This
, nIndex
, nValue
);
1605 return FACTAudioEngine_SetGlobalVariable(This
->fact_engine
, nIndex
, nValue
);
1608 static HRESULT WINAPI
IXACT3EngineImpl_GetGlobalVariable(IXACT3Engine
*iface
,
1609 XACTVARIABLEINDEX nIndex
, XACTVARIABLEVALUE
*nValue
)
1611 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1613 TRACE("(%p)->(%u, %p)\n", This
, nIndex
, nValue
);
1615 return FACTAudioEngine_GetGlobalVariable(This
->fact_engine
, nIndex
, nValue
);
1618 static const IXACT3EngineVtbl XACT3Engine_Vtbl
=
1620 IXACT3EngineImpl_QueryInterface
,
1621 IXACT3EngineImpl_AddRef
,
1622 IXACT3EngineImpl_Release
,
1623 IXACT3EngineImpl_GetRendererCount
,
1624 IXACT3EngineImpl_GetRendererDetails
,
1625 #if XACT3_VER >= 0x0205
1626 IXACT3EngineImpl_GetFinalMixFormat
,
1628 IXACT3EngineImpl_Initialize
,
1629 IXACT3EngineImpl_ShutDown
,
1630 IXACT3EngineImpl_DoWork
,
1631 IXACT3EngineImpl_CreateSoundBank
,
1632 IXACT3EngineImpl_CreateInMemoryWaveBank
,
1633 IXACT3EngineImpl_CreateStreamingWaveBank
,
1634 #if XACT3_VER >= 0x0205
1635 IXACT3EngineImpl_PrepareWave
,
1636 IXACT3EngineImpl_PrepareInMemoryWave
,
1637 IXACT3EngineImpl_PrepareStreamingWave
,
1639 IXACT3EngineImpl_RegisterNotification
,
1640 IXACT3EngineImpl_UnRegisterNotification
,
1641 IXACT3EngineImpl_GetCategory
,
1642 IXACT3EngineImpl_Stop
,
1643 IXACT3EngineImpl_SetVolume
,
1644 IXACT3EngineImpl_Pause
,
1645 IXACT3EngineImpl_GetGlobalVariableIndex
,
1646 IXACT3EngineImpl_SetGlobalVariable
,
1647 IXACT3EngineImpl_GetGlobalVariable
1650 void* XACT_Internal_Malloc(size_t size
)
1652 return CoTaskMemAlloc(size
);
1655 void XACT_Internal_Free(void* ptr
)
1657 return CoTaskMemFree(ptr
);
1660 void* XACT_Internal_Realloc(void* ptr
, size_t size
)
1662 return CoTaskMemRealloc(ptr
, size
);
1665 static HRESULT WINAPI
XACT3CF_QueryInterface(IClassFactory
*iface
, REFIID riid
, void **ppobj
)
1667 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
1668 IsEqualGUID(riid
, &IID_IClassFactory
))
1675 WARN("(%p)->(%s, %p): interface not found\n", iface
, debugstr_guid(riid
), ppobj
);
1676 return E_NOINTERFACE
;
1679 static ULONG WINAPI
XACT3CF_AddRef(IClassFactory
*iface
)
1684 static ULONG WINAPI
XACT3CF_Release(IClassFactory
*iface
)
1689 static HRESULT WINAPI
XACT3CF_CreateInstance(IClassFactory
*iface
, IUnknown
*pOuter
,
1690 REFIID riid
, void **ppobj
)
1693 XACT3EngineImpl
*object
;
1695 TRACE("(%p)->(%p,%s,%p)\n", iface
, pOuter
, debugstr_guid(riid
), ppobj
);
1700 return CLASS_E_NOAGGREGATION
;
1702 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1704 return E_OUTOFMEMORY
;
1706 object
->IXACT3Engine_iface
.lpVtbl
= &XACT3Engine_Vtbl
;
1708 FACTCreateEngineWithCustomAllocatorEXT(
1710 &object
->fact_engine
,
1711 XACT_Internal_Malloc
,
1713 XACT_Internal_Realloc
1716 hr
= IXACT3Engine_QueryInterface(&object
->IXACT3Engine_iface
, riid
, ppobj
);
1718 HeapFree(GetProcessHeap(), 0, object
);
1722 wine_rb_init(&object
->wrapper_lookup
, wrapper_lookup_compare
);
1723 InitializeCriticalSection(&object
->wrapper_lookup_cs
);
1728 static HRESULT WINAPI
XACT3CF_LockServer(IClassFactory
*iface
, BOOL dolock
)
1730 TRACE("(%p)->(%d): stub!\n", iface
, dolock
);
1734 static const IClassFactoryVtbl XACT3CF_Vtbl
=
1736 XACT3CF_QueryInterface
,
1739 XACT3CF_CreateInstance
,
1743 static IClassFactory XACTFactory
= { &XACT3CF_Vtbl
};
1745 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD reason
, void *pReserved
)
1747 TRACE("(%p, %ld, %p)\n", hinstDLL
, reason
, pReserved
);
1751 case DLL_PROCESS_ATTACH
:
1752 DisableThreadLibraryCalls( hinstDLL
);
1753 TRACE("Using FAudio version %d\n", FAudioLinkedVersion() );
1759 HRESULT WINAPI
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, void **ppv
)
1761 if (IsEqualGUID(rclsid
, &CLSID_XACTEngine
))
1763 TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid
), debugstr_guid(riid
), ppv
);
1764 return IClassFactory_QueryInterface(&XACTFactory
, riid
, ppv
);
1767 FIXME("Unknown class %s\n", debugstr_guid(rclsid
));
1768 return CLASS_E_CLASSNOTAVAILABLE
;