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
25 #if XACT3_VER < 0x0300
35 #include "wine/debug.h"
36 #include "wine/rbtree.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(xaudio2
);
40 #if XACT3_VER < 0x0300
41 #define IID_IXACT3Engine IID_IXACTEngine
42 #define IXACT3Cue IXACTCue
43 #define IXACT3CueVtbl IXACTCueVtbl
44 #define IXACT3Engine IXACTEngine
45 #define IXACT3EngineVtbl IXACTEngineVtbl
46 #define IXACT3Engine_QueryInterface IXACTEngine_QueryInterface
47 #define IXACT3SoundBank IXACTSoundBank
48 #define IXACT3SoundBankVtbl IXACTSoundBankVtbl
49 #define IXACT3Wave IXACTWave
50 #define IXACT3WaveVtbl IXACTWaveVtbl
51 #define IXACT3WaveBank IXACTWaveBank
52 #define IXACT3WaveBankVtbl IXACTWaveBankVtbl
55 #define XACTNOTIFICATIONTYPE_MAX 19 /* XACTNOTIFICATIONTYPE_WAVEBANKSTREAMING_INVALIDCONTENT + 1 */
59 struct wine_rb_entry entry
;
64 typedef struct _XACT3EngineImpl
{
65 IXACT3Engine IXACT3Engine_iface
;
67 FACTAudioEngine
*fact_engine
;
69 XACT_READFILE_CALLBACK pReadFile
;
70 XACT_GETOVERLAPPEDRESULT_CALLBACK pGetOverlappedResult
;
71 XACT_NOTIFICATION_CALLBACK notification_callback
;
73 void *contexts
[XACTNOTIFICATIONTYPE_MAX
];
74 struct wine_rb_tree wrapper_lookup
;
75 CRITICAL_SECTION wrapper_lookup_cs
;
78 static int wrapper_lookup_compare(const void *key
, const struct wine_rb_entry
*entry
)
80 struct wrapper_lookup
*lookup
= WINE_RB_ENTRY_VALUE(entry
, struct wrapper_lookup
, entry
);
82 return (key
> lookup
->fact
) - (key
< lookup
->fact
);
85 static void wrapper_lookup_destroy(struct wine_rb_entry
*entry
, void *context
)
87 struct wrapper_lookup
*lookup
= WINE_RB_ENTRY_VALUE(entry
, struct wrapper_lookup
, entry
);
89 HeapFree(GetProcessHeap(), 0, lookup
);
92 static void wrapper_remove_entry(XACT3EngineImpl
*engine
, void *key
)
94 struct wrapper_lookup
*lookup
;
95 struct wine_rb_entry
*entry
;
97 EnterCriticalSection(&engine
->wrapper_lookup_cs
);
99 entry
= wine_rb_get(&engine
->wrapper_lookup
, key
);
102 LeaveCriticalSection(&engine
->wrapper_lookup_cs
);
104 WARN("cannot find key in wrapper lookup\n");
108 wine_rb_remove(&engine
->wrapper_lookup
, entry
);
110 LeaveCriticalSection(&engine
->wrapper_lookup_cs
);
112 lookup
= WINE_RB_ENTRY_VALUE(entry
, struct wrapper_lookup
, entry
);
113 HeapFree(GetProcessHeap(), 0, lookup
);
117 static HRESULT
wrapper_add_entry(XACT3EngineImpl
*engine
, void *fact
, void *xact
)
119 struct wrapper_lookup
*lookup
;
122 lookup
= HeapAlloc(GetProcessHeap(), 0, sizeof(*lookup
));
125 ERR("Failed to allocate wrapper_lookup!\n");
126 return E_OUTOFMEMORY
;
131 EnterCriticalSection(&engine
->wrapper_lookup_cs
);
132 ret
= wine_rb_put(&engine
->wrapper_lookup
, lookup
->fact
, &lookup
->entry
);
133 LeaveCriticalSection(&engine
->wrapper_lookup_cs
);
137 WARN("wrapper_lookup already present in the tree??\n");
138 HeapFree(GetProcessHeap(), 0, lookup
);
144 /* Must be protected by engine->wrapper_lookup_cs */
145 static void* wrapper_find_entry(XACT3EngineImpl
*engine
, void *faudio
)
147 struct wrapper_lookup
*lookup
;
148 struct wine_rb_entry
*entry
;
150 entry
= wine_rb_get(&engine
->wrapper_lookup
, faudio
);
153 lookup
= WINE_RB_ENTRY_VALUE(entry
, struct wrapper_lookup
, entry
);
157 WARN("cannot find interface in wrapper lookup\n");
161 typedef struct _XACT3CueImpl
{
162 IXACT3Cue IXACT3Cue_iface
;
164 XACT3EngineImpl
*engine
;
167 static inline XACT3CueImpl
*impl_from_IXACT3Cue(IXACT3Cue
*iface
)
169 return CONTAINING_RECORD(iface
, XACT3CueImpl
, IXACT3Cue_iface
);
172 static HRESULT WINAPI
IXACT3CueImpl_Play(IXACT3Cue
*iface
)
174 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
176 TRACE("(%p)\n", iface
);
178 return FACTCue_Play(This
->fact_cue
);
181 static HRESULT WINAPI
IXACT3CueImpl_Stop(IXACT3Cue
*iface
, DWORD dwFlags
)
183 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
185 TRACE("(%p)->(%lu)\n", iface
, dwFlags
);
187 return FACTCue_Stop(This
->fact_cue
, dwFlags
);
190 static HRESULT WINAPI
IXACT3CueImpl_GetState(IXACT3Cue
*iface
, DWORD
*pdwState
)
192 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
194 TRACE("(%p)->(%p)\n", iface
, pdwState
);
196 return FACTCue_GetState(This
->fact_cue
, (uint32_t *)pdwState
);
199 static HRESULT WINAPI
IXACT3CueImpl_Destroy(IXACT3Cue
*iface
)
201 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
204 TRACE("(%p)\n", iface
);
206 ret
= FACTCue_Destroy(This
->fact_cue
);
208 WARN("FACTCue_Destroy returned %d\n", ret
);
209 wrapper_remove_entry(This
->engine
, This
->fact_cue
);
210 HeapFree(GetProcessHeap(), 0, This
);
214 #if XACT3_VER < 0x0300
216 static HRESULT WINAPI
IXACT3CueImpl_GetChannelMap(IXACT3Cue
*iface
,
217 XACTCHANNELMAP
*map
, DWORD size
, DWORD
*needed_size
)
219 FIXME("(%p)->(%p, %lu, %p)\n", iface
, map
, size
, needed_size
);
224 static HRESULT WINAPI
IXACT3CueImpl_SetChannelMap(IXACT3Cue
*iface
, XACTCHANNELMAP
*map
)
226 FIXME("(%p)->(%p)\n", iface
, map
);
231 static HRESULT WINAPI
IXACT3CueImpl_GetChannelVolume(IXACT3Cue
*iface
, XACTCHANNELVOLUME
*volume
)
233 FIXME("(%p)->(%p)\n", iface
, volume
);
238 static HRESULT WINAPI
IXACT3CueImpl_SetChannelVolume(IXACT3Cue
*iface
, XACTCHANNELVOLUME
*volume
)
240 FIXME("(%p)->(%p)\n", iface
, volume
);
247 static HRESULT WINAPI
IXACT3CueImpl_SetMatrixCoefficients(IXACT3Cue
*iface
,
248 UINT32 uSrcChannelCount
, UINT32 uDstChannelCount
,
249 float *pMatrixCoefficients
)
251 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
253 TRACE("(%p)->(%u, %u, %p)\n", iface
, uSrcChannelCount
, uDstChannelCount
,
254 pMatrixCoefficients
);
256 return FACTCue_SetMatrixCoefficients(This
->fact_cue
, uSrcChannelCount
,
257 uDstChannelCount
, pMatrixCoefficients
);
260 static XACTVARIABLEINDEX WINAPI
IXACT3CueImpl_GetVariableIndex(IXACT3Cue
*iface
,
261 PCSTR szFriendlyName
)
263 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
265 TRACE("(%p)->(%s)\n", iface
, szFriendlyName
);
267 return FACTCue_GetVariableIndex(This
->fact_cue
, szFriendlyName
);
270 static HRESULT WINAPI
IXACT3CueImpl_SetVariable(IXACT3Cue
*iface
,
271 XACTVARIABLEINDEX nIndex
, XACTVARIABLEVALUE nValue
)
273 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
275 TRACE("(%p)->(%u, %f)\n", iface
, nIndex
, nValue
);
277 return FACTCue_SetVariable(This
->fact_cue
, nIndex
, nValue
);
280 static HRESULT WINAPI
IXACT3CueImpl_GetVariable(IXACT3Cue
*iface
,
281 XACTVARIABLEINDEX nIndex
, XACTVARIABLEVALUE
*nValue
)
283 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
285 TRACE("(%p)->(%u, %p)\n", iface
, nIndex
, nValue
);
287 return FACTCue_GetVariable(This
->fact_cue
, nIndex
, nValue
);
290 static HRESULT WINAPI
IXACT3CueImpl_Pause(IXACT3Cue
*iface
, BOOL fPause
)
292 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
294 TRACE("(%p)->(%u)\n", iface
, fPause
);
296 return FACTCue_Pause(This
->fact_cue
, fPause
);
299 #if XACT3_VER >= 0x0205
300 static HRESULT WINAPI
IXACT3CueImpl_GetProperties(IXACT3Cue
*iface
,
301 XACT_CUE_INSTANCE_PROPERTIES
**ppProperties
)
303 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
304 FACTCueInstanceProperties
*fProps
;
307 TRACE("(%p)->(%p)\n", iface
, ppProperties
);
309 hr
= FACTCue_GetProperties(This
->fact_cue
, &fProps
);
313 *ppProperties
= (XACT_CUE_INSTANCE_PROPERTIES
*) fProps
;
318 #if XACT3_VER >= 0x0305
319 static HRESULT WINAPI
IXACT3CueImpl_SetOutputVoices(IXACT3Cue
*iface
,
320 const XAUDIO2_VOICE_SENDS
*pSendList
)
322 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
323 FIXME("(%p)->(%p): stub!\n", This
, pSendList
);
327 static HRESULT WINAPI
IXACT3CueImpl_SetOutputVoiceMatrix(IXACT3Cue
*iface
,
328 IXAudio2Voice
*pDestinationVoice
, UINT32 SourceChannels
,
329 UINT32 DestinationChannels
, const float *pLevelMatrix
)
331 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
332 FIXME("(%p)->(%p %u %u %p): stub!\n", This
, pDestinationVoice
, SourceChannels
,
333 DestinationChannels
, pLevelMatrix
);
338 static const IXACT3CueVtbl XACT3Cue_Vtbl
=
342 IXACT3CueImpl_GetState
,
343 IXACT3CueImpl_Destroy
,
344 #if XACT3_VER < 0x0300
345 IXACT3CueImpl_GetChannelMap
,
346 IXACT3CueImpl_SetChannelMap
,
347 IXACT3CueImpl_GetChannelVolume
,
348 IXACT3CueImpl_SetChannelVolume
,
350 IXACT3CueImpl_SetMatrixCoefficients
,
351 IXACT3CueImpl_GetVariableIndex
,
352 IXACT3CueImpl_SetVariable
,
353 IXACT3CueImpl_GetVariable
,
355 #if XACT3_VER >= 0x0205
356 IXACT3CueImpl_GetProperties
,
358 #if XACT3_VER >= 0x0305
359 IXACT3CueImpl_SetOutputVoices
,
360 IXACT3CueImpl_SetOutputVoiceMatrix
364 typedef struct _XACT3SoundBankImpl
{
365 IXACT3SoundBank IXACT3SoundBank_iface
;
367 FACTSoundBank
*fact_soundbank
;
368 XACT3EngineImpl
*engine
;
369 } XACT3SoundBankImpl
;
371 static inline XACT3SoundBankImpl
*impl_from_IXACT3SoundBank(IXACT3SoundBank
*iface
)
373 return CONTAINING_RECORD(iface
, XACT3SoundBankImpl
, IXACT3SoundBank_iface
);
376 static XACTINDEX WINAPI
IXACT3SoundBankImpl_GetCueIndex(IXACT3SoundBank
*iface
,
377 PCSTR szFriendlyName
)
379 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
381 TRACE("(%p)->(%s)\n", This
, szFriendlyName
);
383 return FACTSoundBank_GetCueIndex(This
->fact_soundbank
, szFriendlyName
);
386 #if XACT3_VER >= 0x0205
387 static HRESULT WINAPI
IXACT3SoundBankImpl_GetNumCues(IXACT3SoundBank
*iface
,
388 XACTINDEX
*pnNumCues
)
390 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
392 TRACE("(%p)->(%p)\n", This
, pnNumCues
);
394 return FACTSoundBank_GetNumCues(This
->fact_soundbank
, pnNumCues
);
397 static HRESULT WINAPI
IXACT3SoundBankImpl_GetCueProperties(IXACT3SoundBank
*iface
,
398 XACTINDEX nCueIndex
, XACT_CUE_PROPERTIES
*pProperties
)
400 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
402 TRACE("(%p)->(%u, %p)\n", This
, nCueIndex
, pProperties
);
404 return FACTSoundBank_GetCueProperties(This
->fact_soundbank
, nCueIndex
,
405 (FACTCueProperties
*) pProperties
);
409 static HRESULT WINAPI
IXACT3SoundBankImpl_Prepare(IXACT3SoundBank
*iface
,
410 XACTINDEX nCueIndex
, DWORD dwFlags
, XACTTIME timeOffset
,
413 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
419 TRACE("(%p)->(%u, 0x%lx, %lu, %p)\n", This
, nCueIndex
, dwFlags
, timeOffset
,
422 ret
= FACTSoundBank_Prepare(This
->fact_soundbank
, nCueIndex
, dwFlags
,
426 ERR("Failed to CreateCue: %d\n", ret
);
430 cue
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*cue
));
433 FACTCue_Destroy(fcue
);
434 ERR("Failed to allocate XACT3CueImpl!\n");
435 return E_OUTOFMEMORY
;
438 hr
= wrapper_add_entry(This
->engine
, fcue
, &cue
->IXACT3Cue_iface
);
441 FACTCue_Destroy(fcue
);
442 HeapFree(GetProcessHeap(), 0, cue
);
446 cue
->IXACT3Cue_iface
.lpVtbl
= &XACT3Cue_Vtbl
;
447 cue
->fact_cue
= fcue
;
448 cue
->engine
= This
->engine
;
449 *ppCue
= &cue
->IXACT3Cue_iface
;
451 TRACE("Created Cue: %p\n", cue
);
456 static HRESULT WINAPI
IXACT3SoundBankImpl_Play(IXACT3SoundBank
*iface
,
457 XACTINDEX nCueIndex
, DWORD dwFlags
, XACTTIME timeOffset
,
460 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
465 TRACE("(%p)->(%u, 0x%lx, %lu, %p)\n", This
, nCueIndex
, dwFlags
, timeOffset
,
468 /* If the application doesn't want a handle, don't generate one at all.
469 * Let the engine handle that memory instead.
473 hr
= FACTSoundBank_Play(This
->fact_soundbank
, nCueIndex
, dwFlags
,
476 hr
= FACTSoundBank_Play(This
->fact_soundbank
, nCueIndex
, dwFlags
,
481 cue
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*cue
));
484 FACTCue_Destroy(fcue
);
485 ERR("Failed to allocate XACT3CueImpl!\n");
486 return E_OUTOFMEMORY
;
489 hr
= wrapper_add_entry(This
->engine
, fcue
, &cue
->IXACT3Cue_iface
);
492 FACTCue_Destroy(fcue
);
493 HeapFree(GetProcessHeap(), 0, cue
);
497 cue
->IXACT3Cue_iface
.lpVtbl
= &XACT3Cue_Vtbl
;
498 cue
->fact_cue
= fcue
;
499 cue
->engine
= This
->engine
;
500 *ppCue
= &cue
->IXACT3Cue_iface
;
506 static HRESULT WINAPI
IXACT3SoundBankImpl_Stop(IXACT3SoundBank
*iface
,
507 XACTINDEX nCueIndex
, DWORD dwFlags
)
509 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
511 TRACE("(%p)->(%lu)\n", This
, dwFlags
);
513 return FACTSoundBank_Stop(This
->fact_soundbank
, nCueIndex
, dwFlags
);
516 static HRESULT WINAPI
IXACT3SoundBankImpl_Destroy(IXACT3SoundBank
*iface
)
518 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
521 TRACE("(%p)\n", This
);
523 hr
= FACTSoundBank_Destroy(This
->fact_soundbank
);
525 wrapper_remove_entry(This
->engine
, This
->fact_soundbank
);
526 HeapFree(GetProcessHeap(), 0, This
);
530 static HRESULT WINAPI
IXACT3SoundBankImpl_GetState(IXACT3SoundBank
*iface
,
533 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
535 TRACE("(%p)->(%p)\n", This
, pdwState
);
537 return FACTSoundBank_GetState(This
->fact_soundbank
, (uint32_t *)pdwState
);
540 static const IXACT3SoundBankVtbl XACT3SoundBank_Vtbl
=
542 IXACT3SoundBankImpl_GetCueIndex
,
543 #if XACT3_VER >= 0x0205
544 IXACT3SoundBankImpl_GetNumCues
,
545 IXACT3SoundBankImpl_GetCueProperties
,
547 IXACT3SoundBankImpl_Prepare
,
548 IXACT3SoundBankImpl_Play
,
549 IXACT3SoundBankImpl_Stop
,
550 IXACT3SoundBankImpl_Destroy
,
551 IXACT3SoundBankImpl_GetState
554 #if XACT3_VER >= 0x0205
556 typedef struct _XACT3WaveImpl
{
557 IXACT3Wave IXACT3Wave_iface
;
560 XACT3EngineImpl
*engine
;
563 static inline XACT3WaveImpl
*impl_from_IXACT3Wave(IXACT3Wave
*iface
)
565 return CONTAINING_RECORD(iface
, XACT3WaveImpl
, IXACT3Wave_iface
);
568 static HRESULT WINAPI
IXACT3WaveImpl_Destroy(IXACT3Wave
*iface
)
570 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
573 TRACE("(%p)\n", This
);
575 hr
= FACTWave_Destroy(This
->fact_wave
);
576 wrapper_remove_entry(This
->engine
, This
->fact_wave
);
577 HeapFree(GetProcessHeap(), 0, This
);
581 static HRESULT WINAPI
IXACT3WaveImpl_Play(IXACT3Wave
*iface
)
583 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
585 TRACE("(%p)\n", This
);
587 return FACTWave_Play(This
->fact_wave
);
590 static HRESULT WINAPI
IXACT3WaveImpl_Stop(IXACT3Wave
*iface
, DWORD dwFlags
)
592 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
594 TRACE("(%p)->(0x%lx)\n", This
, dwFlags
);
596 return FACTWave_Stop(This
->fact_wave
, dwFlags
);
599 static HRESULT WINAPI
IXACT3WaveImpl_Pause(IXACT3Wave
*iface
, BOOL fPause
)
601 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
603 TRACE("(%p)->(%u)\n", This
, fPause
);
605 return FACTWave_Pause(This
->fact_wave
, fPause
);
608 static HRESULT WINAPI
IXACT3WaveImpl_GetState(IXACT3Wave
*iface
, DWORD
*pdwState
)
610 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
612 TRACE("(%p)->(%p)\n", This
, pdwState
);
614 return FACTWave_GetState(This
->fact_wave
, (uint32_t *)pdwState
);
617 static HRESULT WINAPI
IXACT3WaveImpl_SetPitch(IXACT3Wave
*iface
, XACTPITCH pitch
)
619 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
621 TRACE("(%p)->(%d)\n", This
, pitch
);
623 return FACTWave_SetPitch(This
->fact_wave
, pitch
);
626 static HRESULT WINAPI
IXACT3WaveImpl_SetVolume(IXACT3Wave
*iface
, XACTVOLUME volume
)
628 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
630 TRACE("(%p)->(%f)\n", This
, volume
);
632 return FACTWave_SetVolume(This
->fact_wave
, volume
);
635 static HRESULT WINAPI
IXACT3WaveImpl_SetMatrixCoefficients(IXACT3Wave
*iface
,
636 UINT32 uSrcChannelCount
, UINT32 uDstChannelCount
,
637 float *pMatrixCoefficients
)
639 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
641 TRACE("(%p)->(%u, %u, %p)\n", This
, uSrcChannelCount
, uDstChannelCount
,
642 pMatrixCoefficients
);
644 return FACTWave_SetMatrixCoefficients(This
->fact_wave
, uSrcChannelCount
,
645 uDstChannelCount
, pMatrixCoefficients
);
648 static HRESULT WINAPI
IXACT3WaveImpl_GetProperties(IXACT3Wave
*iface
,
649 XACT_WAVE_INSTANCE_PROPERTIES
*pProperties
)
651 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
653 TRACE("(%p)->(%p)\n", This
, pProperties
);
655 return FACTWave_GetProperties(This
->fact_wave
,
656 (FACTWaveInstanceProperties
*) pProperties
);
659 static const IXACT3WaveVtbl XACT3Wave_Vtbl
=
661 IXACT3WaveImpl_Destroy
,
664 IXACT3WaveImpl_Pause
,
665 IXACT3WaveImpl_GetState
,
666 IXACT3WaveImpl_SetPitch
,
667 IXACT3WaveImpl_SetVolume
,
668 IXACT3WaveImpl_SetMatrixCoefficients
,
669 IXACT3WaveImpl_GetProperties
674 typedef struct _XACT3WaveBankImpl
{
675 IXACT3WaveBank IXACT3WaveBank_iface
;
677 FACTWaveBank
*fact_wavebank
;
678 struct _XACT3EngineImpl
*engine
;
681 static inline XACT3WaveBankImpl
*impl_from_IXACT3WaveBank(IXACT3WaveBank
*iface
)
683 return CONTAINING_RECORD(iface
, XACT3WaveBankImpl
, IXACT3WaveBank_iface
);
686 static HRESULT WINAPI
IXACT3WaveBankImpl_Destroy(IXACT3WaveBank
*iface
)
688 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
691 TRACE("(%p)\n", This
);
693 hr
= FACTWaveBank_Destroy(This
->fact_wavebank
);
695 wrapper_remove_entry(This
->engine
, This
->fact_wavebank
);
697 HeapFree(GetProcessHeap(), 0, This
);
701 #if XACT3_VER >= 0x0205
703 static HRESULT WINAPI
IXACT3WaveBankImpl_GetNumWaves(IXACT3WaveBank
*iface
,
704 XACTINDEX
*pnNumWaves
)
706 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
708 TRACE("(%p)->(%p)\n", This
, pnNumWaves
);
710 return FACTWaveBank_GetNumWaves(This
->fact_wavebank
, pnNumWaves
);
713 static XACTINDEX WINAPI
IXACT3WaveBankImpl_GetWaveIndex(IXACT3WaveBank
*iface
,
714 PCSTR szFriendlyName
)
716 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
718 TRACE("(%p)->(%s)\n", This
, szFriendlyName
);
720 return FACTWaveBank_GetWaveIndex(This
->fact_wavebank
, szFriendlyName
);
723 static HRESULT WINAPI
IXACT3WaveBankImpl_GetWaveProperties(IXACT3WaveBank
*iface
,
724 XACTINDEX nWaveIndex
, XACT_WAVE_PROPERTIES
*pWaveProperties
)
726 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
728 TRACE("(%p)->(%u, %p)\n", This
, nWaveIndex
, pWaveProperties
);
730 return FACTWaveBank_GetWaveProperties(This
->fact_wavebank
, nWaveIndex
,
731 (FACTWaveProperties
*) pWaveProperties
);
734 static HRESULT WINAPI
IXACT3WaveBankImpl_Prepare(IXACT3WaveBank
*iface
,
735 XACTINDEX nWaveIndex
, DWORD dwFlags
, DWORD dwPlayOffset
,
736 XACTLOOPCOUNT nLoopCount
, IXACT3Wave
** ppWave
)
738 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
744 TRACE("(%p)->(0x%x, %lu, 0x%lx, %u, %p)\n", This
, nWaveIndex
, dwFlags
,
745 dwPlayOffset
, nLoopCount
, ppWave
);
747 ret
= FACTWaveBank_Prepare(This
->fact_wavebank
, nWaveIndex
, dwFlags
,
748 dwPlayOffset
, nLoopCount
, &fwave
);
751 ERR("Failed to CreateWave: %d\n", ret
);
755 wave
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*wave
));
758 FACTWave_Destroy(fwave
);
759 ERR("Failed to allocate XACT3WaveImpl!\n");
760 return E_OUTOFMEMORY
;
763 hr
= wrapper_add_entry(This
->engine
, fwave
, &wave
->IXACT3Wave_iface
);
766 FACTWave_Destroy(fwave
);
767 HeapFree(GetProcessHeap(), 0, wave
);
771 wave
->IXACT3Wave_iface
.lpVtbl
= &XACT3Wave_Vtbl
;
772 wave
->fact_wave
= fwave
;
773 wave
->engine
= This
->engine
;
774 *ppWave
= &wave
->IXACT3Wave_iface
;
776 TRACE("Created Wave: %p\n", wave
);
781 static HRESULT WINAPI
IXACT3WaveBankImpl_Play(IXACT3WaveBank
*iface
,
782 XACTINDEX nWaveIndex
, DWORD dwFlags
, DWORD dwPlayOffset
,
783 XACTLOOPCOUNT nLoopCount
, IXACT3Wave
** ppWave
)
785 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
790 TRACE("(%p)->(0x%x, %lu, 0x%lx, %u, %p)\n", This
, nWaveIndex
, dwFlags
, dwPlayOffset
,
793 /* If the application doesn't want a handle, don't generate one at all.
794 * Let the engine handle that memory instead.
798 hr
= FACTWaveBank_Play(This
->fact_wavebank
, nWaveIndex
, dwFlags
,
799 dwPlayOffset
, nLoopCount
, NULL
);
801 hr
= FACTWaveBank_Play(This
->fact_wavebank
, nWaveIndex
, dwFlags
,
802 dwPlayOffset
, nLoopCount
, &fwave
);
806 wave
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*wave
));
809 FACTWave_Destroy(fwave
);
810 ERR("Failed to allocate XACT3WaveImpl!\n");
811 return E_OUTOFMEMORY
;
814 hr
= wrapper_add_entry(This
->engine
, fwave
, &wave
->IXACT3Wave_iface
);
817 FACTWave_Destroy(fwave
);
818 HeapFree(GetProcessHeap(), 0, wave
);
822 wave
->IXACT3Wave_iface
.lpVtbl
= &XACT3Wave_Vtbl
;
823 wave
->fact_wave
= fwave
;
824 wave
->engine
= This
->engine
;
825 *ppWave
= &wave
->IXACT3Wave_iface
;
831 static HRESULT WINAPI
IXACT3WaveBankImpl_Stop(IXACT3WaveBank
*iface
,
832 XACTINDEX nWaveIndex
, DWORD dwFlags
)
834 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
836 TRACE("(%p)->(%u, %lu)\n", This
, nWaveIndex
, dwFlags
);
838 return FACTWaveBank_Stop(This
->fact_wavebank
, nWaveIndex
, dwFlags
);
843 static HRESULT WINAPI
IXACT3WaveBankImpl_GetState(IXACT3WaveBank
*iface
,
846 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
848 TRACE("(%p)->(%p)\n", This
, pdwState
);
850 return FACTWaveBank_GetState(This
->fact_wavebank
, (uint32_t *)pdwState
);
853 static const IXACT3WaveBankVtbl XACT3WaveBank_Vtbl
=
855 IXACT3WaveBankImpl_Destroy
,
856 #if XACT3_VER >= 0x0205
857 IXACT3WaveBankImpl_GetNumWaves
,
858 IXACT3WaveBankImpl_GetWaveIndex
,
859 IXACT3WaveBankImpl_GetWaveProperties
,
860 IXACT3WaveBankImpl_Prepare
,
861 IXACT3WaveBankImpl_Play
,
862 IXACT3WaveBankImpl_Stop
,
864 IXACT3WaveBankImpl_GetState
867 typedef struct wrap_readfile_struct
{
868 XACT3EngineImpl
*engine
;
870 } wrap_readfile_struct
;
872 static int32_t FACTCALL
wrap_readfile(
875 uint32_t nNumberOfBytesRead
,
876 uint32_t *lpNumberOfBytesRead
,
877 FACTOverlapped
*lpOverlapped
)
879 wrap_readfile_struct
*wrap
= (wrap_readfile_struct
*) hFile
;
880 return wrap
->engine
->pReadFile(wrap
->file
, lpBuffer
, nNumberOfBytesRead
,
881 (DWORD
*)lpNumberOfBytesRead
, (LPOVERLAPPED
)lpOverlapped
);
884 static int32_t FACTCALL
wrap_getoverlappedresult(
886 FACTOverlapped
*lpOverlapped
,
887 uint32_t *lpNumberOfBytesTransferred
,
890 wrap_readfile_struct
*wrap
= (wrap_readfile_struct
*) hFile
;
891 return wrap
->engine
->pGetOverlappedResult(wrap
->file
, (LPOVERLAPPED
)lpOverlapped
,
892 (DWORD
*)lpNumberOfBytesTransferred
, bWait
);
895 static inline XACT3EngineImpl
*impl_from_IXACT3Engine(IXACT3Engine
*iface
)
897 return CONTAINING_RECORD(iface
, XACT3EngineImpl
, IXACT3Engine_iface
);
900 static HRESULT WINAPI
IXACT3EngineImpl_QueryInterface(IXACT3Engine
*iface
,
901 REFIID riid
, void **ppvObject
)
903 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
905 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
907 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
908 IsEqualGUID(riid
, &IID_IXACT3Engine
)){
909 *ppvObject
= &This
->IXACT3Engine_iface
;
915 IUnknown_AddRef((IUnknown
*)*ppvObject
);
919 FIXME("(%p)->(%s,%p), not found\n", This
, debugstr_guid(riid
), ppvObject
);
921 return E_NOINTERFACE
;
924 static ULONG WINAPI
IXACT3EngineImpl_AddRef(IXACT3Engine
*iface
)
926 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
927 ULONG ref
= FACTAudioEngine_AddRef(This
->fact_engine
);
928 TRACE("(%p)->(): Refcount now %lu\n", This
, ref
);
932 static ULONG WINAPI
IXACT3EngineImpl_Release(IXACT3Engine
*iface
)
934 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
935 ULONG ref
= FACTAudioEngine_Release(This
->fact_engine
);
937 TRACE("(%p)->(): Refcount now %lu\n", This
, ref
);
941 DeleteCriticalSection(&This
->wrapper_lookup_cs
);
942 wine_rb_destroy(&This
->wrapper_lookup
, wrapper_lookup_destroy
, NULL
);
943 HeapFree(GetProcessHeap(), 0, This
);
948 static HRESULT WINAPI
IXACT3EngineImpl_GetRendererCount(IXACT3Engine
*iface
,
949 XACTINDEX
*pnRendererCount
)
951 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
953 TRACE("(%p)->(%p)\n", This
, pnRendererCount
);
955 return FACTAudioEngine_GetRendererCount(This
->fact_engine
, pnRendererCount
);
958 static HRESULT WINAPI
IXACT3EngineImpl_GetRendererDetails(IXACT3Engine
*iface
,
959 XACTINDEX nRendererIndex
, XACT_RENDERER_DETAILS
*pRendererDetails
)
961 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
963 TRACE("(%p)->(%d, %p)\n", This
, nRendererIndex
, pRendererDetails
);
965 return FACTAudioEngine_GetRendererDetails(This
->fact_engine
,
966 nRendererIndex
, (FACTRendererDetails
*) pRendererDetails
);
969 #if XACT3_VER >= 0x0205
971 static HRESULT WINAPI
IXACT3EngineImpl_GetFinalMixFormat(IXACT3Engine
*iface
,
972 WAVEFORMATEXTENSIBLE
*pFinalMixFormat
)
974 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
976 TRACE("(%p)->(%p)\n", This
, pFinalMixFormat
);
978 return FACTAudioEngine_GetFinalMixFormat(This
->fact_engine
,
979 (FAudioWaveFormatExtensible
*) pFinalMixFormat
);
984 static XACTNOTIFICATIONTYPE
xact_notification_type_from_fact(uint8_t type
)
986 /* we can't use a switch statement, because the constants are static const
987 * variables, and some compilers can't deal with that */
988 #define X(a) if (type == FACTNOTIFICATIONTYPE_##a) return XACTNOTIFICATIONTYPE_##a
994 X(SOUNDBANKDESTROYED
);
995 X(WAVEBANKDESTROYED
);
996 X(LOCALVARIABLECHANGED
);
997 X(GLOBALVARIABLECHANGED
);
1002 X(WAVEBANKPREPARED
);
1003 X(WAVEBANKSTREAMING_INVALIDCONTENT
);
1004 #if XACT3_VER >= 0x0205
1011 FIXME("unknown type %#x\n", type
);
1015 static void FACTCALL
fact_notification_cb(const FACTNotification
*notification
)
1017 XACT3EngineImpl
*engine
= (XACT3EngineImpl
*)notification
->pvContext
;
1018 XACT_NOTIFICATION xnotification
;
1020 TRACE("notification %d, context %p\n", notification
->type
, notification
->pvContext
);
1022 /* Older versions of FAudio don't pass through the context */
1025 WARN("Notification context is NULL\n");
1029 xnotification
.type
= xact_notification_type_from_fact(notification
->type
);
1030 xnotification
.timeStamp
= notification
->timeStamp
;
1031 xnotification
.pvContext
= engine
->contexts
[notification
->type
];
1033 EnterCriticalSection(&engine
->wrapper_lookup_cs
);
1034 if (notification
->type
== XACTNOTIFICATIONTYPE_WAVEBANKPREPARED
1035 || notification
->type
== XACTNOTIFICATIONTYPE_WAVEBANKDESTROYED
)
1037 xnotification
.waveBank
.pWaveBank
= wrapper_find_entry(engine
, notification
->waveBank
.pWaveBank
);
1039 else if(notification
->type
== XACTNOTIFICATIONTYPE_SOUNDBANKDESTROYED
)
1041 xnotification
.soundBank
.pSoundBank
= wrapper_find_entry(engine
, notification
->soundBank
.pSoundBank
);
1043 else if (notification
->type
== XACTNOTIFICATIONTYPE_WAVESTOP
1044 #if XACT3_VER >= 0x0205
1045 || notification
->type
== XACTNOTIFICATIONTYPE_WAVEDESTROYED
1046 || notification
->type
== XACTNOTIFICATIONTYPE_WAVELOOPED
1047 || notification
->type
== XACTNOTIFICATIONTYPE_WAVEPLAY
1048 || notification
->type
== XACTNOTIFICATIONTYPE_WAVEPREPARED
)
1053 xnotification
.wave
.cueIndex
= notification
->wave
.cueIndex
;
1054 xnotification
.wave
.pCue
= wrapper_find_entry(engine
, notification
->wave
.pCue
);
1055 xnotification
.wave
.pSoundBank
= wrapper_find_entry(engine
, notification
->wave
.pSoundBank
);
1056 #if XACT3_VER >= 0x0205
1057 xnotification
.wave
.pWave
= wrapper_find_entry(engine
, notification
->wave
.pWave
);
1059 xnotification
.wave
.pWaveBank
= wrapper_find_entry(engine
, notification
->wave
.pWaveBank
);
1061 else if (notification
->type
== XACTNOTIFICATIONTYPE_CUEPLAY
||
1062 notification
->type
== XACTNOTIFICATIONTYPE_CUEPREPARED
||
1063 notification
->type
== XACTNOTIFICATIONTYPE_CUESTOP
||
1064 notification
->type
== XACTNOTIFICATIONTYPE_CUEDESTROYED
)
1066 xnotification
.cue
.pCue
= wrapper_find_entry(engine
, notification
->cue
.pCue
);
1067 xnotification
.cue
.cueIndex
= notification
->cue
.cueIndex
;
1068 xnotification
.cue
.pSoundBank
= wrapper_find_entry(engine
, notification
->cue
.pSoundBank
);
1072 LeaveCriticalSection(&engine
->wrapper_lookup_cs
);
1073 FIXME("Unsupported callback type %d\n", notification
->type
);
1076 LeaveCriticalSection(&engine
->wrapper_lookup_cs
);
1078 engine
->notification_callback(&xnotification
);
1081 static HRESULT WINAPI
IXACT3EngineImpl_Initialize(IXACT3Engine
*iface
,
1082 const XACT_RUNTIME_PARAMETERS
*pParams
)
1084 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1085 FACTRuntimeParameters params
;
1088 TRACE("(%p)->(%p)\n", This
, pParams
);
1090 memset(¶ms
, 0, sizeof(FACTRuntimeParameters
));
1091 /* Explicitly copy to the FAudio structure as the packing is wrong under 64 bits */
1092 params
.lookAheadTime
= pParams
->lookAheadTime
;
1093 params
.pGlobalSettingsBuffer
= pParams
->pGlobalSettingsBuffer
;
1094 params
.globalSettingsBufferSize
= pParams
->globalSettingsBufferSize
;
1095 params
.globalSettingsFlags
= pParams
->globalSettingsFlags
;
1096 params
.globalSettingsAllocAttributes
= pParams
->globalSettingsAllocAttributes
;
1097 params
.pRendererID
= (int16_t*)pParams
->pRendererID
;
1098 params
.pXAudio2
= NULL
;
1099 params
.pMasteringVoice
= NULL
;
1101 #if XACT3_VER >= 0x0300
1102 /* FIXME: pXAudio2 and pMasteringVoice are pointers to
1103 * IXAudio2/IXAudio2MasteringVoice objects. FACT wants pointers to
1104 * FAudio/FAudioMasteringVoice objects. In Wine's XAudio2 implementation, we
1105 * actually have them available, but only if you access their internal data.
1106 * For now we can just force these pointers to NULL, as XACT simply
1107 * generates its own engine and endpoint in that situation. These parameters
1108 * are mostly an optimization for games with multiple XACT3Engines that want
1109 * a single engine running everything.
1112 if (pParams
->pXAudio2
!= NULL
){
1113 FIXME("pXAudio2 parameter not supported!\n");
1115 if (pParams
->pMasteringVoice
!= NULL
){
1116 FIXME("pMasteringVoice parameter not supported!\n");
1121 /* Force Windows I/O, do NOT use the FACT default! */
1122 This
->pReadFile
= (XACT_READFILE_CALLBACK
)
1123 pParams
->fileIOCallbacks
.readFileCallback
;
1124 This
->pGetOverlappedResult
= (XACT_GETOVERLAPPEDRESULT_CALLBACK
)
1125 pParams
->fileIOCallbacks
.getOverlappedResultCallback
;
1126 if (This
->pReadFile
== NULL
)
1127 This
->pReadFile
= (XACT_READFILE_CALLBACK
) ReadFile
;
1128 if (This
->pGetOverlappedResult
== NULL
)
1129 This
->pGetOverlappedResult
= (XACT_GETOVERLAPPEDRESULT_CALLBACK
)
1130 GetOverlappedResult
;
1131 params
.fileIOCallbacks
.readFileCallback
= wrap_readfile
;
1132 params
.fileIOCallbacks
.getOverlappedResultCallback
= wrap_getoverlappedresult
;
1133 params
.fnNotificationCallback
= fact_notification_cb
;
1135 This
->notification_callback
= (XACT_NOTIFICATION_CALLBACK
)pParams
->fnNotificationCallback
;
1137 ret
= FACTAudioEngine_Initialize(This
->fact_engine
, ¶ms
);
1139 WARN("FACTAudioEngine_Initialize returned %d\n", ret
);
1141 return !ret
? S_OK
: E_FAIL
;
1144 static HRESULT WINAPI
IXACT3EngineImpl_ShutDown(IXACT3Engine
*iface
)
1146 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1148 TRACE("(%p)\n", This
);
1150 return FACTAudioEngine_ShutDown(This
->fact_engine
);
1153 static HRESULT WINAPI
IXACT3EngineImpl_DoWork(IXACT3Engine
*iface
)
1155 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1157 TRACE("(%p)\n", This
);
1159 return FACTAudioEngine_DoWork(This
->fact_engine
);
1162 static HRESULT WINAPI
IXACT3EngineImpl_CreateSoundBank(IXACT3Engine
*iface
,
1163 const void* pvBuffer
, DWORD dwSize
, DWORD dwFlags
,
1164 DWORD dwAllocAttributes
, IXACT3SoundBank
**ppSoundBank
)
1166 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1167 XACT3SoundBankImpl
*sb
;
1172 TRACE("(%p)->(%p, %lu, 0x%lx, 0x%lx, %p)\n", This
, pvBuffer
, dwSize
, dwFlags
,
1173 dwAllocAttributes
, ppSoundBank
);
1175 ret
= FACTAudioEngine_CreateSoundBank(This
->fact_engine
, pvBuffer
, dwSize
,
1176 dwFlags
, dwAllocAttributes
, &fsb
);
1179 ERR("Failed to CreateSoundBank: %d\n", ret
);
1183 sb
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*sb
));
1186 FACTSoundBank_Destroy(fsb
);
1187 ERR("Failed to allocate XACT3SoundBankImpl!\n");
1188 return E_OUTOFMEMORY
;
1191 hr
= wrapper_add_entry(This
, fsb
, &sb
->IXACT3SoundBank_iface
);
1194 FACTSoundBank_Destroy(fsb
);
1195 HeapFree(GetProcessHeap(), 0, sb
);
1199 sb
->IXACT3SoundBank_iface
.lpVtbl
= &XACT3SoundBank_Vtbl
;
1200 sb
->fact_soundbank
= fsb
;
1202 *ppSoundBank
= &sb
->IXACT3SoundBank_iface
;
1204 TRACE("Created SoundBank: %p\n", sb
);
1209 static HRESULT WINAPI
IXACT3EngineImpl_CreateInMemoryWaveBank(IXACT3Engine
*iface
,
1210 const void* pvBuffer
, DWORD dwSize
, DWORD dwFlags
,
1211 DWORD dwAllocAttributes
, IXACT3WaveBank
**ppWaveBank
)
1213 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1214 XACT3WaveBankImpl
*wb
;
1219 TRACE("(%p)->(%p, %lu, 0x%lx, 0x%lx, %p)\n", This
, pvBuffer
, dwSize
, dwFlags
,
1220 dwAllocAttributes
, ppWaveBank
);
1222 ret
= FACTAudioEngine_CreateInMemoryWaveBank(This
->fact_engine
, pvBuffer
,
1223 dwSize
, dwFlags
, dwAllocAttributes
, &fwb
);
1226 ERR("Failed to CreateWaveBank: %d\n", ret
);
1230 wb
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*wb
));
1233 FACTWaveBank_Destroy(fwb
);
1234 ERR("Failed to allocate XACT3WaveBankImpl!\n");
1235 return E_OUTOFMEMORY
;
1238 hr
= wrapper_add_entry(This
, fwb
, &wb
->IXACT3WaveBank_iface
);
1241 FACTWaveBank_Destroy(fwb
);
1242 HeapFree(GetProcessHeap(), 0, wb
);
1246 wb
->IXACT3WaveBank_iface
.lpVtbl
= &XACT3WaveBank_Vtbl
;
1247 wb
->fact_wavebank
= fwb
;
1249 *ppWaveBank
= &wb
->IXACT3WaveBank_iface
;
1251 TRACE("Created in-memory WaveBank: %p\n", wb
);
1256 static HRESULT WINAPI
IXACT3EngineImpl_CreateStreamingWaveBank(IXACT3Engine
*iface
,
1257 const XACT_WAVEBANK_STREAMING_PARAMETERS
*pParms
,
1258 IXACT3WaveBank
**ppWaveBank
)
1260 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1261 FACTStreamingParameters fakeParms
;
1262 wrap_readfile_struct
*fake
;
1263 XACT3WaveBankImpl
*wb
;
1268 TRACE("(%p)->(%p, %p)\n", This
, pParms
, ppWaveBank
);
1270 /* We have to wrap the file to fix up the callbacks! */
1271 fake
= (wrap_readfile_struct
*) CoTaskMemAlloc(
1272 sizeof(wrap_readfile_struct
));
1273 fake
->engine
= This
;
1274 fake
->file
= pParms
->file
;
1275 fakeParms
.file
= fake
;
1276 fakeParms
.flags
= pParms
->flags
;
1277 fakeParms
.offset
= pParms
->offset
;
1278 fakeParms
.packetSize
= pParms
->packetSize
;
1280 ret
= FACTAudioEngine_CreateStreamingWaveBank(This
->fact_engine
, &fakeParms
,
1284 ERR("Failed to CreateWaveBank: %d\n", ret
);
1288 wb
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*wb
));
1291 FACTWaveBank_Destroy(fwb
);
1292 ERR("Failed to allocate XACT3WaveBankImpl!\n");
1293 return E_OUTOFMEMORY
;
1296 hr
= wrapper_add_entry(This
, fwb
, &wb
->IXACT3WaveBank_iface
);
1299 FACTWaveBank_Destroy(fwb
);
1300 HeapFree(GetProcessHeap(), 0, wb
);
1304 wb
->IXACT3WaveBank_iface
.lpVtbl
= &XACT3WaveBank_Vtbl
;
1305 wb
->fact_wavebank
= fwb
;
1307 *ppWaveBank
= &wb
->IXACT3WaveBank_iface
;
1309 TRACE("Created streaming WaveBank: %p\n", wb
);
1314 #if XACT3_VER >= 0x0205
1316 static HRESULT WINAPI
IXACT3EngineImpl_PrepareInMemoryWave(IXACT3Engine
*iface
,
1317 DWORD dwFlags
, WAVEBANKENTRY entry
, DWORD
*pdwSeekTable
,
1318 BYTE
*pbWaveData
, DWORD dwPlayOffset
, XACTLOOPCOUNT nLoopCount
,
1319 IXACT3Wave
**ppWave
)
1321 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1322 FIXME("(%p): stub!\n", This
);
1326 static HRESULT WINAPI
IXACT3EngineImpl_PrepareStreamingWave(IXACT3Engine
*iface
,
1327 DWORD dwFlags
, WAVEBANKENTRY entry
,
1328 XACT_STREAMING_PARAMETERS streamingParams
, DWORD dwAlignment
,
1329 DWORD
*pdwSeekTable
, DWORD dwPlayOffset
, XACTLOOPCOUNT nLoopCount
,
1330 IXACT3Wave
**ppWave
)
1332 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1333 FIXME("(%p): stub!\n", This
);
1337 static HRESULT WINAPI
IXACT3EngineImpl_PrepareWave(IXACT3Engine
*iface
,
1338 DWORD dwFlags
, PCSTR szWavePath
, WORD wStreamingPacketSize
,
1339 DWORD dwAlignment
, DWORD dwPlayOffset
, XACTLOOPCOUNT nLoopCount
,
1340 IXACT3Wave
**ppWave
)
1342 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1343 XACT3WaveImpl
*wave
;
1344 FACTWave
*fwave
= NULL
;
1348 TRACE("(%p)->(0x%08lx, %s, %d, %ld, %ld, %d, %p)\n", This
, dwFlags
, debugstr_a(szWavePath
),
1349 wStreamingPacketSize
, dwAlignment
, dwPlayOffset
, nLoopCount
, ppWave
);
1351 ret
= FACTAudioEngine_PrepareWave(This
->fact_engine
, dwFlags
, szWavePath
, wStreamingPacketSize
,
1352 dwAlignment
, dwPlayOffset
, nLoopCount
, &fwave
);
1353 if(ret
!= 0 || !fwave
)
1355 ERR("Failed to CreateWave: %d (%p)\n", ret
, fwave
);
1359 wave
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*wave
));
1362 FACTWave_Destroy(fwave
);
1363 return E_OUTOFMEMORY
;
1366 hr
= wrapper_add_entry(This
, fwave
, &wave
->IXACT3Wave_iface
);
1369 FACTWave_Destroy(fwave
);
1370 HeapFree(GetProcessHeap(), 0, wave
);
1374 wave
->IXACT3Wave_iface
.lpVtbl
= &XACT3Wave_Vtbl
;
1375 wave
->fact_wave
= fwave
;
1376 wave
->engine
= This
;
1377 *ppWave
= &wave
->IXACT3Wave_iface
;
1379 TRACE("Created Wave: %p\n", wave
);
1387 NOTIFY_SoundBank
= 0x01,
1388 NOTIFY_WaveBank
= 0x02,
1391 NOTIFY_cueIndex
= 0x10,
1392 NOTIFY_waveIndex
= 0x20
1395 /* these constants don't have the same values across xactengine versions */
1396 static uint8_t fact_notification_type_from_xact(XACTNOTIFICATIONTYPE type
)
1398 /* we can't use a switch statement, because the constants are static const
1399 * variables, and some compilers can't deal with that */
1400 #define X(a) if (type == XACTNOTIFICATIONTYPE_##a) return FACTNOTIFICATIONTYPE_##a
1406 X(SOUNDBANKDESTROYED
);
1407 X(WAVEBANKDESTROYED
);
1408 X(LOCALVARIABLECHANGED
);
1409 X(GLOBALVARIABLECHANGED
);
1414 X(WAVEBANKPREPARED
);
1415 X(WAVEBANKSTREAMING_INVALIDCONTENT
);
1416 #if XACT3_VER >= 0x0205
1423 FIXME("unknown type %#x\n", type
);
1427 static inline void unwrap_notificationdesc(FACTNotificationDescription
*fd
,
1428 const XACT_NOTIFICATION_DESCRIPTION
*xd
)
1432 TRACE("Type %d\n", xd
->type
);
1434 memset(fd
, 0, sizeof(*fd
));
1436 fd
->type
= fact_notification_type_from_xact(xd
->type
);
1438 /* we can't use a switch statement, because the constants are static const
1439 * variables, and some compilers can't deal with that */
1441 /* Supports SoundBank, Cue index, Cue instance */
1442 if (fd
->type
== FACTNOTIFICATIONTYPE_CUEPREPARED
|| fd
->type
== FACTNOTIFICATIONTYPE_CUEPLAY
||
1443 fd
->type
== FACTNOTIFICATIONTYPE_CUESTOP
|| fd
->type
== FACTNOTIFICATIONTYPE_CUEDESTROYED
||
1444 fd
->type
== FACTNOTIFICATIONTYPE_MARKER
|| fd
->type
== FACTNOTIFICATIONTYPE_LOCALVARIABLECHANGED
)
1446 flags
= NOTIFY_SoundBank
| NOTIFY_cueIndex
| NOTIFY_Cue
;
1448 /* Supports WaveBank */
1449 else if (fd
->type
== FACTNOTIFICATIONTYPE_WAVEBANKDESTROYED
|| fd
->type
== FACTNOTIFICATIONTYPE_WAVEBANKPREPARED
||
1450 fd
->type
== FACTNOTIFICATIONTYPE_WAVEBANKSTREAMING_INVALIDCONTENT
)
1452 flags
= NOTIFY_WaveBank
;
1454 /* Supports NOTIFY_SoundBank */
1455 else if (fd
->type
== FACTNOTIFICATIONTYPE_SOUNDBANKDESTROYED
)
1457 flags
= NOTIFY_SoundBank
;
1459 /* Supports SoundBank, SoundBank, Cue index, Cue instance, WaveBank, Wave instance */
1460 else if (fd
->type
== FACTNOTIFICATIONTYPE_WAVEPLAY
|| fd
->type
== FACTNOTIFICATIONTYPE_WAVESTOP
||
1461 fd
->type
== FACTNOTIFICATIONTYPE_WAVELOOPED
)
1463 flags
= NOTIFY_SoundBank
| NOTIFY_cueIndex
| NOTIFY_Cue
| NOTIFY_WaveBank
| NOTIFY_Wave
;
1465 /* Supports WaveBank, Wave index, Wave instance */
1466 else if (fd
->type
== FACTNOTIFICATIONTYPE_WAVEPREPARED
|| fd
->type
== FACTNOTIFICATIONTYPE_WAVEDESTROYED
)
1468 flags
= NOTIFY_WaveBank
| NOTIFY_waveIndex
| NOTIFY_Wave
;
1471 /* We have to unwrap the FACT object first! */
1472 fd
->flags
= xd
->flags
;
1473 if (flags
& NOTIFY_cueIndex
)
1474 fd
->cueIndex
= xd
->cueIndex
;
1475 #if XACT3_VER >= 0x0205
1476 if (flags
& NOTIFY_waveIndex
)
1477 fd
->waveIndex
= xd
->waveIndex
;
1480 if (flags
& NOTIFY_Cue
&& xd
->pCue
!= NULL
)
1482 XACT3CueImpl
*cue
= impl_from_IXACT3Cue(xd
->pCue
);
1484 fd
->pCue
= cue
->fact_cue
;
1487 if (flags
& NOTIFY_SoundBank
&& xd
->pSoundBank
!= NULL
)
1489 XACT3SoundBankImpl
*sound
= impl_from_IXACT3SoundBank(xd
->pSoundBank
);
1491 fd
->pSoundBank
= sound
->fact_soundbank
;
1494 if (flags
& NOTIFY_WaveBank
&& xd
->pWaveBank
!= NULL
)
1496 XACT3WaveBankImpl
*bank
= impl_from_IXACT3WaveBank(xd
->pWaveBank
);
1498 fd
->pWaveBank
= bank
->fact_wavebank
;
1501 #if XACT3_VER >= 0x0205
1502 if (flags
& NOTIFY_Wave
&& xd
->pWave
!= NULL
)
1504 XACT3WaveImpl
*wave
= impl_from_IXACT3Wave(xd
->pWave
);
1506 fd
->pWave
= wave
->fact_wave
;
1511 static HRESULT WINAPI
IXACT3EngineImpl_RegisterNotification(IXACT3Engine
*iface
,
1512 const XACT_NOTIFICATION_DESCRIPTION
*pNotificationDesc
)
1514 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1515 FACTNotificationDescription fdesc
;
1517 TRACE("(%p)->(%p)\n", This
, pNotificationDesc
);
1519 if (pNotificationDesc
->type
< XACTNOTIFICATIONTYPE_CUEPREPARED
||
1520 pNotificationDesc
->type
> XACTNOTIFICATIONTYPE_WAVEBANKSTREAMING_INVALIDCONTENT
)
1521 return E_INVALIDARG
;
1523 unwrap_notificationdesc(&fdesc
, pNotificationDesc
);
1524 This
->contexts
[pNotificationDesc
->type
] = pNotificationDesc
->pvContext
;
1525 fdesc
.pvContext
= This
;
1526 return FACTAudioEngine_RegisterNotification(This
->fact_engine
, &fdesc
);
1529 static HRESULT WINAPI
IXACT3EngineImpl_UnRegisterNotification(IXACT3Engine
*iface
,
1530 const XACT_NOTIFICATION_DESCRIPTION
*pNotificationDesc
)
1532 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1533 FACTNotificationDescription fdesc
;
1535 TRACE("(%p)->(%p)\n", This
, pNotificationDesc
);
1537 if (pNotificationDesc
->type
< XACTNOTIFICATIONTYPE_CUEPREPARED
||
1538 pNotificationDesc
->type
> XACTNOTIFICATIONTYPE_WAVEBANKSTREAMING_INVALIDCONTENT
)
1541 unwrap_notificationdesc(&fdesc
, pNotificationDesc
);
1542 fdesc
.pvContext
= This
;
1543 return FACTAudioEngine_UnRegisterNotification(This
->fact_engine
, &fdesc
);
1546 static XACTCATEGORY WINAPI
IXACT3EngineImpl_GetCategory(IXACT3Engine
*iface
,
1547 PCSTR szFriendlyName
)
1549 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1551 TRACE("(%p)->(%s)\n", This
, szFriendlyName
);
1553 return FACTAudioEngine_GetCategory(This
->fact_engine
, szFriendlyName
);
1556 static HRESULT WINAPI
IXACT3EngineImpl_Stop(IXACT3Engine
*iface
,
1557 XACTCATEGORY nCategory
, DWORD dwFlags
)
1559 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1561 TRACE("(%p)->(%u, 0x%lx)\n", This
, nCategory
, dwFlags
);
1563 return FACTAudioEngine_Stop(This
->fact_engine
, nCategory
, dwFlags
);
1566 static HRESULT WINAPI
IXACT3EngineImpl_SetVolume(IXACT3Engine
*iface
,
1567 XACTCATEGORY nCategory
, XACTVOLUME nVolume
)
1569 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1571 TRACE("(%p)->(%u, %f)\n", This
, nCategory
, nVolume
);
1573 return FACTAudioEngine_SetVolume(This
->fact_engine
, nCategory
, nVolume
);
1576 static HRESULT WINAPI
IXACT3EngineImpl_Pause(IXACT3Engine
*iface
,
1577 XACTCATEGORY nCategory
, BOOL fPause
)
1579 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1581 TRACE("(%p)->(%u, %u)\n", This
, nCategory
, fPause
);
1583 return FACTAudioEngine_Pause(This
->fact_engine
, nCategory
, fPause
);
1586 static XACTVARIABLEINDEX WINAPI
IXACT3EngineImpl_GetGlobalVariableIndex(
1587 IXACT3Engine
*iface
, PCSTR szFriendlyName
)
1589 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1591 TRACE("(%p)->(%s)\n", This
, szFriendlyName
);
1593 return FACTAudioEngine_GetGlobalVariableIndex(This
->fact_engine
,
1597 static HRESULT WINAPI
IXACT3EngineImpl_SetGlobalVariable(IXACT3Engine
*iface
,
1598 XACTVARIABLEINDEX nIndex
, XACTVARIABLEVALUE nValue
)
1600 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1602 TRACE("(%p)->(%u, %f)\n", This
, nIndex
, nValue
);
1604 return FACTAudioEngine_SetGlobalVariable(This
->fact_engine
, nIndex
, nValue
);
1607 static HRESULT WINAPI
IXACT3EngineImpl_GetGlobalVariable(IXACT3Engine
*iface
,
1608 XACTVARIABLEINDEX nIndex
, XACTVARIABLEVALUE
*nValue
)
1610 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1612 TRACE("(%p)->(%u, %p)\n", This
, nIndex
, nValue
);
1614 return FACTAudioEngine_GetGlobalVariable(This
->fact_engine
, nIndex
, nValue
);
1617 static const IXACT3EngineVtbl XACT3Engine_Vtbl
=
1619 IXACT3EngineImpl_QueryInterface
,
1620 IXACT3EngineImpl_AddRef
,
1621 IXACT3EngineImpl_Release
,
1622 IXACT3EngineImpl_GetRendererCount
,
1623 IXACT3EngineImpl_GetRendererDetails
,
1624 #if XACT3_VER >= 0x0205
1625 IXACT3EngineImpl_GetFinalMixFormat
,
1627 IXACT3EngineImpl_Initialize
,
1628 IXACT3EngineImpl_ShutDown
,
1629 IXACT3EngineImpl_DoWork
,
1630 IXACT3EngineImpl_CreateSoundBank
,
1631 IXACT3EngineImpl_CreateInMemoryWaveBank
,
1632 IXACT3EngineImpl_CreateStreamingWaveBank
,
1633 #if XACT3_VER >= 0x0205
1634 IXACT3EngineImpl_PrepareWave
,
1635 IXACT3EngineImpl_PrepareInMemoryWave
,
1636 IXACT3EngineImpl_PrepareStreamingWave
,
1638 IXACT3EngineImpl_RegisterNotification
,
1639 IXACT3EngineImpl_UnRegisterNotification
,
1640 IXACT3EngineImpl_GetCategory
,
1641 IXACT3EngineImpl_Stop
,
1642 IXACT3EngineImpl_SetVolume
,
1643 IXACT3EngineImpl_Pause
,
1644 IXACT3EngineImpl_GetGlobalVariableIndex
,
1645 IXACT3EngineImpl_SetGlobalVariable
,
1646 IXACT3EngineImpl_GetGlobalVariable
1649 void* XACT_Internal_Malloc(size_t size
)
1651 return CoTaskMemAlloc(size
);
1654 void XACT_Internal_Free(void* ptr
)
1656 return CoTaskMemFree(ptr
);
1659 void* XACT_Internal_Realloc(void* ptr
, size_t size
)
1661 return CoTaskMemRealloc(ptr
, size
);
1664 static HRESULT WINAPI
XACT3CF_QueryInterface(IClassFactory
*iface
, REFIID riid
, void **ppobj
)
1666 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
1667 IsEqualGUID(riid
, &IID_IClassFactory
))
1674 WARN("(%p)->(%s, %p): interface not found\n", iface
, debugstr_guid(riid
), ppobj
);
1675 return E_NOINTERFACE
;
1678 static ULONG WINAPI
XACT3CF_AddRef(IClassFactory
*iface
)
1683 static ULONG WINAPI
XACT3CF_Release(IClassFactory
*iface
)
1688 static HRESULT WINAPI
XACT3CF_CreateInstance(IClassFactory
*iface
, IUnknown
*pOuter
,
1689 REFIID riid
, void **ppobj
)
1692 XACT3EngineImpl
*object
;
1694 TRACE("(%p)->(%p,%s,%p)\n", iface
, pOuter
, debugstr_guid(riid
), ppobj
);
1699 return CLASS_E_NOAGGREGATION
;
1701 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1703 return E_OUTOFMEMORY
;
1705 object
->IXACT3Engine_iface
.lpVtbl
= &XACT3Engine_Vtbl
;
1707 FACTCreateEngineWithCustomAllocatorEXT(
1709 &object
->fact_engine
,
1710 XACT_Internal_Malloc
,
1712 XACT_Internal_Realloc
1715 hr
= IXACT3Engine_QueryInterface(&object
->IXACT3Engine_iface
, riid
, ppobj
);
1717 HeapFree(GetProcessHeap(), 0, object
);
1721 wine_rb_init(&object
->wrapper_lookup
, wrapper_lookup_compare
);
1722 InitializeCriticalSection(&object
->wrapper_lookup_cs
);
1727 static HRESULT WINAPI
XACT3CF_LockServer(IClassFactory
*iface
, BOOL dolock
)
1729 TRACE("(%p)->(%d): stub!\n", iface
, dolock
);
1733 static const IClassFactoryVtbl XACT3CF_Vtbl
=
1735 XACT3CF_QueryInterface
,
1738 XACT3CF_CreateInstance
,
1742 static IClassFactory XACTFactory
= { &XACT3CF_Vtbl
};
1744 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD reason
, void *pReserved
)
1746 TRACE("(%p, %ld, %p)\n", hinstDLL
, reason
, pReserved
);
1750 case DLL_PROCESS_ATTACH
:
1751 DisableThreadLibraryCalls( hinstDLL
);
1752 TRACE("Using FAudio version %d\n", FAudioLinkedVersion() );
1758 HRESULT WINAPI
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, void **ppv
)
1760 if (IsEqualGUID(rclsid
, &CLSID_XACTEngine
))
1762 TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid
), debugstr_guid(riid
), ppv
);
1763 return IClassFactory_QueryInterface(&XACTFactory
, riid
, ppv
);
1766 FIXME("Unknown class %s\n", debugstr_guid(rclsid
));
1767 return CLASS_E_CLASSNOTAVAILABLE
;