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(xact3
);
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
58 struct wine_rb_entry entry
;
63 typedef struct _XACT3EngineImpl
{
64 IXACT3Engine IXACT3Engine_iface
;
66 FACTAudioEngine
*fact_engine
;
68 XACT_READFILE_CALLBACK pReadFile
;
69 XACT_GETOVERLAPPEDRESULT_CALLBACK pGetOverlappedResult
;
70 XACT_NOTIFICATION_CALLBACK notification_callback
;
72 void *wb_prepared_context
;
73 void *wb_destroyed_context
;
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 typedef struct _XACT3CueImpl
{
145 IXACT3Cue IXACT3Cue_iface
;
147 XACT3EngineImpl
*engine
;
150 static inline XACT3CueImpl
*impl_from_IXACT3Cue(IXACT3Cue
*iface
)
152 return CONTAINING_RECORD(iface
, XACT3CueImpl
, IXACT3Cue_iface
);
155 static HRESULT WINAPI
IXACT3CueImpl_Play(IXACT3Cue
*iface
)
157 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
159 TRACE("(%p)\n", iface
);
161 return FACTCue_Play(This
->fact_cue
);
164 static HRESULT WINAPI
IXACT3CueImpl_Stop(IXACT3Cue
*iface
, DWORD dwFlags
)
166 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
168 TRACE("(%p)->(%lu)\n", iface
, dwFlags
);
170 return FACTCue_Stop(This
->fact_cue
, dwFlags
);
173 static HRESULT WINAPI
IXACT3CueImpl_GetState(IXACT3Cue
*iface
, DWORD
*pdwState
)
175 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
177 TRACE("(%p)->(%p)\n", iface
, pdwState
);
179 return FACTCue_GetState(This
->fact_cue
, (uint32_t *)pdwState
);
182 static HRESULT WINAPI
IXACT3CueImpl_Destroy(IXACT3Cue
*iface
)
184 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
187 TRACE("(%p)\n", iface
);
189 ret
= FACTCue_Destroy(This
->fact_cue
);
191 WARN("FACTCue_Destroy returned %d\n", ret
);
192 wrapper_remove_entry(This
->engine
, This
->fact_cue
);
193 HeapFree(GetProcessHeap(), 0, This
);
197 #if XACT3_VER < 0x0300
199 static HRESULT WINAPI
IXACT3CueImpl_GetChannelMap(IXACT3Cue
*iface
,
200 XACTCHANNELMAP
*map
, DWORD size
, DWORD
*needed_size
)
202 FIXME("(%p)->(%p, %lu, %p)\n", iface
, map
, size
, needed_size
);
207 static HRESULT WINAPI
IXACT3CueImpl_SetChannelMap(IXACT3Cue
*iface
, XACTCHANNELMAP
*map
)
209 FIXME("(%p)->(%p)\n", iface
, map
);
214 static HRESULT WINAPI
IXACT3CueImpl_GetChannelVolume(IXACT3Cue
*iface
, XACTCHANNELVOLUME
*volume
)
216 FIXME("(%p)->(%p)\n", iface
, volume
);
221 static HRESULT WINAPI
IXACT3CueImpl_SetChannelVolume(IXACT3Cue
*iface
, XACTCHANNELVOLUME
*volume
)
223 FIXME("(%p)->(%p)\n", iface
, volume
);
230 static HRESULT WINAPI
IXACT3CueImpl_SetMatrixCoefficients(IXACT3Cue
*iface
,
231 UINT32 uSrcChannelCount
, UINT32 uDstChannelCount
,
232 float *pMatrixCoefficients
)
234 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
236 TRACE("(%p)->(%u, %u, %p)\n", iface
, uSrcChannelCount
, uDstChannelCount
,
237 pMatrixCoefficients
);
239 return FACTCue_SetMatrixCoefficients(This
->fact_cue
, uSrcChannelCount
,
240 uDstChannelCount
, pMatrixCoefficients
);
243 static XACTVARIABLEINDEX WINAPI
IXACT3CueImpl_GetVariableIndex(IXACT3Cue
*iface
,
244 PCSTR szFriendlyName
)
246 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
248 TRACE("(%p)->(%s)\n", iface
, szFriendlyName
);
250 return FACTCue_GetVariableIndex(This
->fact_cue
, szFriendlyName
);
253 static HRESULT WINAPI
IXACT3CueImpl_SetVariable(IXACT3Cue
*iface
,
254 XACTVARIABLEINDEX nIndex
, XACTVARIABLEVALUE nValue
)
256 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
258 TRACE("(%p)->(%u, %f)\n", iface
, nIndex
, nValue
);
260 return FACTCue_SetVariable(This
->fact_cue
, nIndex
, nValue
);
263 static HRESULT WINAPI
IXACT3CueImpl_GetVariable(IXACT3Cue
*iface
,
264 XACTVARIABLEINDEX nIndex
, XACTVARIABLEVALUE
*nValue
)
266 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
268 TRACE("(%p)->(%u, %p)\n", iface
, nIndex
, nValue
);
270 return FACTCue_GetVariable(This
->fact_cue
, nIndex
, nValue
);
273 static HRESULT WINAPI
IXACT3CueImpl_Pause(IXACT3Cue
*iface
, BOOL fPause
)
275 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
277 TRACE("(%p)->(%u)\n", iface
, fPause
);
279 return FACTCue_Pause(This
->fact_cue
, fPause
);
282 #if XACT3_VER >= 0x0205
283 static HRESULT WINAPI
IXACT3CueImpl_GetProperties(IXACT3Cue
*iface
,
284 XACT_CUE_INSTANCE_PROPERTIES
**ppProperties
)
286 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
287 FACTCueInstanceProperties
*fProps
;
290 TRACE("(%p)->(%p)\n", iface
, ppProperties
);
292 hr
= FACTCue_GetProperties(This
->fact_cue
, &fProps
);
296 *ppProperties
= (XACT_CUE_INSTANCE_PROPERTIES
*) fProps
;
301 #if XACT3_VER >= 0x0300
302 static HRESULT WINAPI
IXACT3CueImpl_SetOutputVoices(IXACT3Cue
*iface
,
303 const XAUDIO2_VOICE_SENDS
*pSendList
)
305 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
306 FIXME("(%p)->(%p): stub!\n", This
, pSendList
);
310 static HRESULT WINAPI
IXACT3CueImpl_SetOutputVoiceMatrix(IXACT3Cue
*iface
,
311 IXAudio2Voice
*pDestinationVoice
, UINT32 SourceChannels
,
312 UINT32 DestinationChannels
, const float *pLevelMatrix
)
314 XACT3CueImpl
*This
= impl_from_IXACT3Cue(iface
);
315 FIXME("(%p)->(%p %u %u %p): stub!\n", This
, pDestinationVoice
, SourceChannels
,
316 DestinationChannels
, pLevelMatrix
);
321 static const IXACT3CueVtbl XACT3Cue_Vtbl
=
325 IXACT3CueImpl_GetState
,
326 IXACT3CueImpl_Destroy
,
327 #if XACT3_VER < 0x0300
328 IXACT3CueImpl_GetChannelMap
,
329 IXACT3CueImpl_SetChannelMap
,
330 IXACT3CueImpl_GetChannelVolume
,
331 IXACT3CueImpl_SetChannelVolume
,
333 IXACT3CueImpl_SetMatrixCoefficients
,
334 IXACT3CueImpl_GetVariableIndex
,
335 IXACT3CueImpl_SetVariable
,
336 IXACT3CueImpl_GetVariable
,
338 #if XACT3_VER >= 0x0205
339 IXACT3CueImpl_GetProperties
,
341 #if XACT3_VER >= 0x0300
342 IXACT3CueImpl_SetOutputVoices
,
343 IXACT3CueImpl_SetOutputVoiceMatrix
347 typedef struct _XACT3SoundBankImpl
{
348 IXACT3SoundBank IXACT3SoundBank_iface
;
350 FACTSoundBank
*fact_soundbank
;
351 XACT3EngineImpl
*engine
;
352 } XACT3SoundBankImpl
;
354 static inline XACT3SoundBankImpl
*impl_from_IXACT3SoundBank(IXACT3SoundBank
*iface
)
356 return CONTAINING_RECORD(iface
, XACT3SoundBankImpl
, IXACT3SoundBank_iface
);
359 static XACTINDEX WINAPI
IXACT3SoundBankImpl_GetCueIndex(IXACT3SoundBank
*iface
,
360 PCSTR szFriendlyName
)
362 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
364 TRACE("(%p)->(%s)\n", This
, szFriendlyName
);
366 return FACTSoundBank_GetCueIndex(This
->fact_soundbank
, szFriendlyName
);
369 #if XACT3_VER >= 0x0205
370 static HRESULT WINAPI
IXACT3SoundBankImpl_GetNumCues(IXACT3SoundBank
*iface
,
371 XACTINDEX
*pnNumCues
)
373 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
375 TRACE("(%p)->(%p)\n", This
, pnNumCues
);
377 return FACTSoundBank_GetNumCues(This
->fact_soundbank
, pnNumCues
);
380 static HRESULT WINAPI
IXACT3SoundBankImpl_GetCueProperties(IXACT3SoundBank
*iface
,
381 XACTINDEX nCueIndex
, XACT_CUE_PROPERTIES
*pProperties
)
383 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
385 TRACE("(%p)->(%u, %p)\n", This
, nCueIndex
, pProperties
);
387 return FACTSoundBank_GetCueProperties(This
->fact_soundbank
, nCueIndex
,
388 (FACTCueProperties
*) pProperties
);
392 static HRESULT WINAPI
IXACT3SoundBankImpl_Prepare(IXACT3SoundBank
*iface
,
393 XACTINDEX nCueIndex
, DWORD dwFlags
, XACTTIME timeOffset
,
396 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
402 TRACE("(%p)->(%u, 0x%lx, %lu, %p)\n", This
, nCueIndex
, dwFlags
, timeOffset
,
405 ret
= FACTSoundBank_Prepare(This
->fact_soundbank
, nCueIndex
, dwFlags
,
409 ERR("Failed to CreateCue: %d\n", ret
);
413 cue
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*cue
));
416 FACTCue_Destroy(fcue
);
417 ERR("Failed to allocate XACT3CueImpl!\n");
418 return E_OUTOFMEMORY
;
421 hr
= wrapper_add_entry(This
->engine
, fcue
, &cue
->IXACT3Cue_iface
);
424 FACTCue_Destroy(fcue
);
425 HeapFree(GetProcessHeap(), 0, cue
);
429 cue
->IXACT3Cue_iface
.lpVtbl
= &XACT3Cue_Vtbl
;
430 cue
->fact_cue
= fcue
;
431 cue
->engine
= This
->engine
;
432 *ppCue
= &cue
->IXACT3Cue_iface
;
434 TRACE("Created Cue: %p\n", cue
);
439 static HRESULT WINAPI
IXACT3SoundBankImpl_Play(IXACT3SoundBank
*iface
,
440 XACTINDEX nCueIndex
, DWORD dwFlags
, XACTTIME timeOffset
,
443 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
448 TRACE("(%p)->(%u, 0x%lx, %lu, %p)\n", This
, nCueIndex
, dwFlags
, timeOffset
,
451 /* If the application doesn't want a handle, don't generate one at all.
452 * Let the engine handle that memory instead.
456 hr
= FACTSoundBank_Play(This
->fact_soundbank
, nCueIndex
, dwFlags
,
459 hr
= FACTSoundBank_Play(This
->fact_soundbank
, nCueIndex
, dwFlags
,
464 cue
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*cue
));
467 FACTCue_Destroy(fcue
);
468 ERR("Failed to allocate XACT3CueImpl!\n");
469 return E_OUTOFMEMORY
;
472 hr
= wrapper_add_entry(This
->engine
, fcue
, &cue
->IXACT3Cue_iface
);
475 FACTCue_Destroy(fcue
);
476 HeapFree(GetProcessHeap(), 0, cue
);
480 cue
->IXACT3Cue_iface
.lpVtbl
= &XACT3Cue_Vtbl
;
481 cue
->fact_cue
= fcue
;
482 cue
->engine
= This
->engine
;
483 *ppCue
= &cue
->IXACT3Cue_iface
;
489 static HRESULT WINAPI
IXACT3SoundBankImpl_Stop(IXACT3SoundBank
*iface
,
490 XACTINDEX nCueIndex
, DWORD dwFlags
)
492 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
494 TRACE("(%p)->(%lu)\n", This
, dwFlags
);
496 return FACTSoundBank_Stop(This
->fact_soundbank
, nCueIndex
, dwFlags
);
499 static HRESULT WINAPI
IXACT3SoundBankImpl_Destroy(IXACT3SoundBank
*iface
)
501 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
504 TRACE("(%p)\n", This
);
506 hr
= FACTSoundBank_Destroy(This
->fact_soundbank
);
508 wrapper_remove_entry(This
->engine
, This
->fact_soundbank
);
509 HeapFree(GetProcessHeap(), 0, This
);
513 static HRESULT WINAPI
IXACT3SoundBankImpl_GetState(IXACT3SoundBank
*iface
,
516 XACT3SoundBankImpl
*This
= impl_from_IXACT3SoundBank(iface
);
518 TRACE("(%p)->(%p)\n", This
, pdwState
);
520 return FACTSoundBank_GetState(This
->fact_soundbank
, (uint32_t *)pdwState
);
523 static const IXACT3SoundBankVtbl XACT3SoundBank_Vtbl
=
525 IXACT3SoundBankImpl_GetCueIndex
,
526 #if XACT3_VER >= 0x0205
527 IXACT3SoundBankImpl_GetNumCues
,
528 IXACT3SoundBankImpl_GetCueProperties
,
530 IXACT3SoundBankImpl_Prepare
,
531 IXACT3SoundBankImpl_Play
,
532 IXACT3SoundBankImpl_Stop
,
533 IXACT3SoundBankImpl_Destroy
,
534 IXACT3SoundBankImpl_GetState
537 #if XACT3_VER >= 0x0205
539 typedef struct _XACT3WaveImpl
{
540 IXACT3Wave IXACT3Wave_iface
;
543 XACT3EngineImpl
*engine
;
546 static inline XACT3WaveImpl
*impl_from_IXACT3Wave(IXACT3Wave
*iface
)
548 return CONTAINING_RECORD(iface
, XACT3WaveImpl
, IXACT3Wave_iface
);
551 static HRESULT WINAPI
IXACT3WaveImpl_Destroy(IXACT3Wave
*iface
)
553 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
556 TRACE("(%p)\n", This
);
558 hr
= FACTWave_Destroy(This
->fact_wave
);
559 wrapper_remove_entry(This
->engine
, This
->fact_wave
);
560 HeapFree(GetProcessHeap(), 0, This
);
564 static HRESULT WINAPI
IXACT3WaveImpl_Play(IXACT3Wave
*iface
)
566 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
568 TRACE("(%p)\n", This
);
570 return FACTWave_Play(This
->fact_wave
);
573 static HRESULT WINAPI
IXACT3WaveImpl_Stop(IXACT3Wave
*iface
, DWORD dwFlags
)
575 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
577 TRACE("(%p)->(0x%lx)\n", This
, dwFlags
);
579 return FACTWave_Stop(This
->fact_wave
, dwFlags
);
582 static HRESULT WINAPI
IXACT3WaveImpl_Pause(IXACT3Wave
*iface
, BOOL fPause
)
584 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
586 TRACE("(%p)->(%u)\n", This
, fPause
);
588 return FACTWave_Pause(This
->fact_wave
, fPause
);
591 static HRESULT WINAPI
IXACT3WaveImpl_GetState(IXACT3Wave
*iface
, DWORD
*pdwState
)
593 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
595 TRACE("(%p)->(%p)\n", This
, pdwState
);
597 return FACTWave_GetState(This
->fact_wave
, (uint32_t *)pdwState
);
600 static HRESULT WINAPI
IXACT3WaveImpl_SetPitch(IXACT3Wave
*iface
, XACTPITCH pitch
)
602 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
604 TRACE("(%p)->(%d)\n", This
, pitch
);
606 return FACTWave_SetPitch(This
->fact_wave
, pitch
);
609 static HRESULT WINAPI
IXACT3WaveImpl_SetVolume(IXACT3Wave
*iface
, XACTVOLUME volume
)
611 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
613 TRACE("(%p)->(%f)\n", This
, volume
);
615 return FACTWave_SetVolume(This
->fact_wave
, volume
);
618 static HRESULT WINAPI
IXACT3WaveImpl_SetMatrixCoefficients(IXACT3Wave
*iface
,
619 UINT32 uSrcChannelCount
, UINT32 uDstChannelCount
,
620 float *pMatrixCoefficients
)
622 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
624 TRACE("(%p)->(%u, %u, %p)\n", This
, uSrcChannelCount
, uDstChannelCount
,
625 pMatrixCoefficients
);
627 return FACTWave_SetMatrixCoefficients(This
->fact_wave
, uSrcChannelCount
,
628 uDstChannelCount
, pMatrixCoefficients
);
631 static HRESULT WINAPI
IXACT3WaveImpl_GetProperties(IXACT3Wave
*iface
,
632 XACT_WAVE_INSTANCE_PROPERTIES
*pProperties
)
634 XACT3WaveImpl
*This
= impl_from_IXACT3Wave(iface
);
636 TRACE("(%p)->(%p)\n", This
, pProperties
);
638 return FACTWave_GetProperties(This
->fact_wave
,
639 (FACTWaveInstanceProperties
*) pProperties
);
642 static const IXACT3WaveVtbl XACT3Wave_Vtbl
=
644 IXACT3WaveImpl_Destroy
,
647 IXACT3WaveImpl_Pause
,
648 IXACT3WaveImpl_GetState
,
649 IXACT3WaveImpl_SetPitch
,
650 IXACT3WaveImpl_SetVolume
,
651 IXACT3WaveImpl_SetMatrixCoefficients
,
652 IXACT3WaveImpl_GetProperties
657 typedef struct _XACT3WaveBankImpl
{
658 IXACT3WaveBank IXACT3WaveBank_iface
;
660 FACTWaveBank
*fact_wavebank
;
661 struct _XACT3EngineImpl
*engine
;
664 static inline XACT3WaveBankImpl
*impl_from_IXACT3WaveBank(IXACT3WaveBank
*iface
)
666 return CONTAINING_RECORD(iface
, XACT3WaveBankImpl
, IXACT3WaveBank_iface
);
669 static HRESULT WINAPI
IXACT3WaveBankImpl_Destroy(IXACT3WaveBank
*iface
)
671 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
674 TRACE("(%p)\n", This
);
676 hr
= FACTWaveBank_Destroy(This
->fact_wavebank
);
678 wrapper_remove_entry(This
->engine
, This
->fact_wavebank
);
680 HeapFree(GetProcessHeap(), 0, This
);
684 #if XACT3_VER >= 0x0205
686 static HRESULT WINAPI
IXACT3WaveBankImpl_GetNumWaves(IXACT3WaveBank
*iface
,
687 XACTINDEX
*pnNumWaves
)
689 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
691 TRACE("(%p)->(%p)\n", This
, pnNumWaves
);
693 return FACTWaveBank_GetNumWaves(This
->fact_wavebank
, pnNumWaves
);
696 static XACTINDEX WINAPI
IXACT3WaveBankImpl_GetWaveIndex(IXACT3WaveBank
*iface
,
697 PCSTR szFriendlyName
)
699 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
701 TRACE("(%p)->(%s)\n", This
, szFriendlyName
);
703 return FACTWaveBank_GetWaveIndex(This
->fact_wavebank
, szFriendlyName
);
706 static HRESULT WINAPI
IXACT3WaveBankImpl_GetWaveProperties(IXACT3WaveBank
*iface
,
707 XACTINDEX nWaveIndex
, XACT_WAVE_PROPERTIES
*pWaveProperties
)
709 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
711 TRACE("(%p)->(%u, %p)\n", This
, nWaveIndex
, pWaveProperties
);
713 return FACTWaveBank_GetWaveProperties(This
->fact_wavebank
, nWaveIndex
,
714 (FACTWaveProperties
*) pWaveProperties
);
717 static HRESULT WINAPI
IXACT3WaveBankImpl_Prepare(IXACT3WaveBank
*iface
,
718 XACTINDEX nWaveIndex
, DWORD dwFlags
, DWORD dwPlayOffset
,
719 XACTLOOPCOUNT nLoopCount
, IXACT3Wave
** ppWave
)
721 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
727 TRACE("(%p)->(0x%x, %lu, 0x%lx, %u, %p)\n", This
, nWaveIndex
, dwFlags
,
728 dwPlayOffset
, nLoopCount
, ppWave
);
730 ret
= FACTWaveBank_Prepare(This
->fact_wavebank
, nWaveIndex
, dwFlags
,
731 dwPlayOffset
, nLoopCount
, &fwave
);
734 ERR("Failed to CreateWave: %d\n", ret
);
738 wave
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*wave
));
741 FACTWave_Destroy(fwave
);
742 ERR("Failed to allocate XACT3WaveImpl!\n");
743 return E_OUTOFMEMORY
;
746 hr
= wrapper_add_entry(This
->engine
, fwave
, &wave
->IXACT3Wave_iface
);
749 FACTWave_Destroy(fwave
);
750 HeapFree(GetProcessHeap(), 0, wave
);
754 wave
->IXACT3Wave_iface
.lpVtbl
= &XACT3Wave_Vtbl
;
755 wave
->fact_wave
= fwave
;
756 wave
->engine
= This
->engine
;
757 *ppWave
= &wave
->IXACT3Wave_iface
;
759 TRACE("Created Wave: %p\n", wave
);
764 static HRESULT WINAPI
IXACT3WaveBankImpl_Play(IXACT3WaveBank
*iface
,
765 XACTINDEX nWaveIndex
, DWORD dwFlags
, DWORD dwPlayOffset
,
766 XACTLOOPCOUNT nLoopCount
, IXACT3Wave
** ppWave
)
768 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
773 TRACE("(%p)->(0x%x, %lu, 0x%lx, %u, %p)\n", This
, nWaveIndex
, dwFlags
, dwPlayOffset
,
776 /* If the application doesn't want a handle, don't generate one at all.
777 * Let the engine handle that memory instead.
781 hr
= FACTWaveBank_Play(This
->fact_wavebank
, nWaveIndex
, dwFlags
,
782 dwPlayOffset
, nLoopCount
, NULL
);
784 hr
= FACTWaveBank_Play(This
->fact_wavebank
, nWaveIndex
, dwFlags
,
785 dwPlayOffset
, nLoopCount
, &fwave
);
789 wave
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*wave
));
792 FACTWave_Destroy(fwave
);
793 ERR("Failed to allocate XACT3WaveImpl!\n");
794 return E_OUTOFMEMORY
;
797 hr
= wrapper_add_entry(This
->engine
, fwave
, &wave
->IXACT3Wave_iface
);
800 FACTWave_Destroy(fwave
);
801 HeapFree(GetProcessHeap(), 0, wave
);
805 wave
->IXACT3Wave_iface
.lpVtbl
= &XACT3Wave_Vtbl
;
806 wave
->fact_wave
= fwave
;
807 wave
->engine
= This
->engine
;
808 *ppWave
= &wave
->IXACT3Wave_iface
;
814 static HRESULT WINAPI
IXACT3WaveBankImpl_Stop(IXACT3WaveBank
*iface
,
815 XACTINDEX nWaveIndex
, DWORD dwFlags
)
817 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
819 TRACE("(%p)->(%u, %lu)\n", This
, nWaveIndex
, dwFlags
);
821 return FACTWaveBank_Stop(This
->fact_wavebank
, nWaveIndex
, dwFlags
);
826 static HRESULT WINAPI
IXACT3WaveBankImpl_GetState(IXACT3WaveBank
*iface
,
829 XACT3WaveBankImpl
*This
= impl_from_IXACT3WaveBank(iface
);
831 TRACE("(%p)->(%p)\n", This
, pdwState
);
833 return FACTWaveBank_GetState(This
->fact_wavebank
, (uint32_t *)pdwState
);
836 static const IXACT3WaveBankVtbl XACT3WaveBank_Vtbl
=
838 IXACT3WaveBankImpl_Destroy
,
839 #if XACT3_VER >= 0x0205
840 IXACT3WaveBankImpl_GetNumWaves
,
841 IXACT3WaveBankImpl_GetWaveIndex
,
842 IXACT3WaveBankImpl_GetWaveProperties
,
843 IXACT3WaveBankImpl_Prepare
,
844 IXACT3WaveBankImpl_Play
,
845 IXACT3WaveBankImpl_Stop
,
847 IXACT3WaveBankImpl_GetState
850 typedef struct wrap_readfile_struct
{
851 XACT3EngineImpl
*engine
;
853 } wrap_readfile_struct
;
855 static int32_t FACTCALL
wrap_readfile(
858 uint32_t nNumberOfBytesRead
,
859 uint32_t *lpNumberOfBytesRead
,
860 FACTOverlapped
*lpOverlapped
)
862 wrap_readfile_struct
*wrap
= (wrap_readfile_struct
*) hFile
;
863 return wrap
->engine
->pReadFile(wrap
->file
, lpBuffer
, nNumberOfBytesRead
,
864 (DWORD
*)lpNumberOfBytesRead
, (LPOVERLAPPED
)lpOverlapped
);
867 static int32_t FACTCALL
wrap_getoverlappedresult(
869 FACTOverlapped
*lpOverlapped
,
870 uint32_t *lpNumberOfBytesTransferred
,
873 wrap_readfile_struct
*wrap
= (wrap_readfile_struct
*) hFile
;
874 return wrap
->engine
->pGetOverlappedResult(wrap
->file
, (LPOVERLAPPED
)lpOverlapped
,
875 (DWORD
*)lpNumberOfBytesTransferred
, bWait
);
878 static inline XACT3EngineImpl
*impl_from_IXACT3Engine(IXACT3Engine
*iface
)
880 return CONTAINING_RECORD(iface
, XACT3EngineImpl
, IXACT3Engine_iface
);
883 static HRESULT WINAPI
IXACT3EngineImpl_QueryInterface(IXACT3Engine
*iface
,
884 REFIID riid
, void **ppvObject
)
886 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
888 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
890 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
891 IsEqualGUID(riid
, &IID_IXACT3Engine
)){
892 *ppvObject
= &This
->IXACT3Engine_iface
;
898 IUnknown_AddRef((IUnknown
*)*ppvObject
);
902 FIXME("(%p)->(%s,%p), not found\n", This
, debugstr_guid(riid
), ppvObject
);
904 return E_NOINTERFACE
;
907 static ULONG WINAPI
IXACT3EngineImpl_AddRef(IXACT3Engine
*iface
)
909 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
910 ULONG ref
= FACTAudioEngine_AddRef(This
->fact_engine
);
911 TRACE("(%p)->(): Refcount now %lu\n", This
, ref
);
915 static ULONG WINAPI
IXACT3EngineImpl_Release(IXACT3Engine
*iface
)
917 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
918 ULONG ref
= FACTAudioEngine_Release(This
->fact_engine
);
920 TRACE("(%p)->(): Refcount now %lu\n", This
, ref
);
924 DeleteCriticalSection(&This
->wrapper_lookup_cs
);
925 wine_rb_destroy(&This
->wrapper_lookup
, wrapper_lookup_destroy
, NULL
);
926 HeapFree(GetProcessHeap(), 0, This
);
931 static HRESULT WINAPI
IXACT3EngineImpl_GetRendererCount(IXACT3Engine
*iface
,
932 XACTINDEX
*pnRendererCount
)
934 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
936 TRACE("(%p)->(%p)\n", This
, pnRendererCount
);
938 return FACTAudioEngine_GetRendererCount(This
->fact_engine
, pnRendererCount
);
941 static HRESULT WINAPI
IXACT3EngineImpl_GetRendererDetails(IXACT3Engine
*iface
,
942 XACTINDEX nRendererIndex
, XACT_RENDERER_DETAILS
*pRendererDetails
)
944 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
946 TRACE("(%p)->(%d, %p)\n", This
, nRendererIndex
, pRendererDetails
);
948 return FACTAudioEngine_GetRendererDetails(This
->fact_engine
,
949 nRendererIndex
, (FACTRendererDetails
*) pRendererDetails
);
952 #if XACT3_VER >= 0x0205
954 static HRESULT WINAPI
IXACT3EngineImpl_GetFinalMixFormat(IXACT3Engine
*iface
,
955 WAVEFORMATEXTENSIBLE
*pFinalMixFormat
)
957 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
959 TRACE("(%p)->(%p)\n", This
, pFinalMixFormat
);
961 return FACTAudioEngine_GetFinalMixFormat(This
->fact_engine
,
962 (FAudioWaveFormatExtensible
*) pFinalMixFormat
);
967 static XACTNOTIFICATIONTYPE
xact_notification_type_from_fact(uint8_t type
)
969 /* we can't use a switch statement, because the constants are static const
970 * variables, and some compilers can't deal with that */
971 #define X(a) if (type == FACTNOTIFICATIONTYPE_##a) return XACTNOTIFICATIONTYPE_##a
977 X(SOUNDBANKDESTROYED
);
978 X(WAVEBANKDESTROYED
);
979 X(LOCALVARIABLECHANGED
);
980 X(GLOBALVARIABLECHANGED
);
986 X(WAVEBANKSTREAMING_INVALIDCONTENT
);
987 #if XACT3_VER >= 0x0205
994 FIXME("unknown type %#x\n", type
);
998 static void FACTCALL
fact_notification_cb(const FACTNotification
*notification
)
1000 XACT3EngineImpl
*engine
= (XACT3EngineImpl
*)notification
->pvContext
;
1001 XACT_NOTIFICATION xnotification
;
1002 struct wrapper_lookup
*lookup
;
1003 struct wine_rb_entry
*entry
;
1005 TRACE("notification %p\n", notification
->pvContext
);
1007 /* Older versions of FAudio don't pass through the context */
1010 WARN("Notification context is NULL\n");
1014 xnotification
.type
= xact_notification_type_from_fact(notification
->type
);
1015 xnotification
.timeStamp
= notification
->timeStamp
;
1017 if (notification
->type
== XACTNOTIFICATIONTYPE_WAVEBANKPREPARED
1018 || notification
->type
== XACTNOTIFICATIONTYPE_WAVEBANKDESTROYED
)
1020 EnterCriticalSection(&engine
->wrapper_lookup_cs
);
1021 entry
= wine_rb_get(&engine
->wrapper_lookup
, notification
->waveBank
.pWaveBank
);
1024 WARN("cannot find wave bank in wrapper lookup\n");
1025 xnotification
.waveBank
.pWaveBank
= NULL
;
1029 lookup
= WINE_RB_ENTRY_VALUE(entry
, struct wrapper_lookup
, entry
);
1030 xnotification
.waveBank
.pWaveBank
= lookup
->xact
;
1032 LeaveCriticalSection(&engine
->wrapper_lookup_cs
);
1033 if (notification
->type
== XACTNOTIFICATIONTYPE_WAVEBANKPREPARED
)
1034 xnotification
.pvContext
= engine
->wb_prepared_context
;
1036 xnotification
.pvContext
= engine
->wb_destroyed_context
;
1040 FIXME("Unsupported callback type %d\n", notification
->type
);
1044 engine
->notification_callback(&xnotification
);
1047 static HRESULT WINAPI
IXACT3EngineImpl_Initialize(IXACT3Engine
*iface
,
1048 const XACT_RUNTIME_PARAMETERS
*pParams
)
1050 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1051 FACTRuntimeParameters params
;
1054 TRACE("(%p)->(%p)\n", This
, pParams
);
1056 memset(¶ms
, 0, sizeof(FACTRuntimeParameters
));
1057 /* Explicitly copy to the FAudio structure as the packing is wrong under 64 bits */
1058 params
.lookAheadTime
= pParams
->lookAheadTime
;
1059 params
.pGlobalSettingsBuffer
= pParams
->pGlobalSettingsBuffer
;
1060 params
.globalSettingsBufferSize
= pParams
->globalSettingsBufferSize
;
1061 params
.globalSettingsFlags
= pParams
->globalSettingsFlags
;
1062 params
.globalSettingsAllocAttributes
= pParams
->globalSettingsAllocAttributes
;
1063 params
.pRendererID
= (int16_t*)pParams
->pRendererID
;
1064 params
.pXAudio2
= NULL
;
1065 params
.pMasteringVoice
= NULL
;
1067 #if XACT3_VER >= 0x0300
1068 /* FIXME: pXAudio2 and pMasteringVoice are pointers to
1069 * IXAudio2/IXAudio2MasteringVoice objects. FACT wants pointers to
1070 * FAudio/FAudioMasteringVoice objects. In Wine's XAudio2 implementation, we
1071 * actually have them available, but only if you access their internal data.
1072 * For now we can just force these pointers to NULL, as XACT simply
1073 * generates its own engine and endpoint in that situation. These parameters
1074 * are mostly an optimization for games with multiple XACT3Engines that want
1075 * a single engine running everything.
1078 if (pParams
->pXAudio2
!= NULL
){
1079 FIXME("pXAudio2 parameter not supported!\n");
1081 if (pParams
->pMasteringVoice
!= NULL
){
1082 FIXME("pMasteringVoice parameter not supported!\n");
1087 /* Force Windows I/O, do NOT use the FACT default! */
1088 This
->pReadFile
= (XACT_READFILE_CALLBACK
)
1089 pParams
->fileIOCallbacks
.readFileCallback
;
1090 This
->pGetOverlappedResult
= (XACT_GETOVERLAPPEDRESULT_CALLBACK
)
1091 pParams
->fileIOCallbacks
.getOverlappedResultCallback
;
1092 if (This
->pReadFile
== NULL
)
1093 This
->pReadFile
= (XACT_READFILE_CALLBACK
) ReadFile
;
1094 if (This
->pGetOverlappedResult
== NULL
)
1095 This
->pGetOverlappedResult
= (XACT_GETOVERLAPPEDRESULT_CALLBACK
)
1096 GetOverlappedResult
;
1097 params
.fileIOCallbacks
.readFileCallback
= wrap_readfile
;
1098 params
.fileIOCallbacks
.getOverlappedResultCallback
= wrap_getoverlappedresult
;
1099 params
.fnNotificationCallback
= fact_notification_cb
;
1101 This
->notification_callback
= (XACT_NOTIFICATION_CALLBACK
)pParams
->fnNotificationCallback
;
1103 ret
= FACTAudioEngine_Initialize(This
->fact_engine
, ¶ms
);
1105 WARN("FACTAudioEngine_Initialize returned %d\n", ret
);
1107 return !ret
? S_OK
: E_FAIL
;
1110 static HRESULT WINAPI
IXACT3EngineImpl_ShutDown(IXACT3Engine
*iface
)
1112 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1114 TRACE("(%p)\n", This
);
1116 return FACTAudioEngine_ShutDown(This
->fact_engine
);
1119 static HRESULT WINAPI
IXACT3EngineImpl_DoWork(IXACT3Engine
*iface
)
1121 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1123 TRACE("(%p)\n", This
);
1125 return FACTAudioEngine_DoWork(This
->fact_engine
);
1128 static HRESULT WINAPI
IXACT3EngineImpl_CreateSoundBank(IXACT3Engine
*iface
,
1129 const void* pvBuffer
, DWORD dwSize
, DWORD dwFlags
,
1130 DWORD dwAllocAttributes
, IXACT3SoundBank
**ppSoundBank
)
1132 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1133 XACT3SoundBankImpl
*sb
;
1138 TRACE("(%p)->(%p, %lu, 0x%lx, 0x%lx, %p): stub!\n", This
, pvBuffer
, dwSize
, dwFlags
,
1139 dwAllocAttributes
, ppSoundBank
);
1141 ret
= FACTAudioEngine_CreateSoundBank(This
->fact_engine
, pvBuffer
, dwSize
,
1142 dwFlags
, dwAllocAttributes
, &fsb
);
1145 ERR("Failed to CreateSoundBank: %d\n", ret
);
1149 sb
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*sb
));
1152 FACTSoundBank_Destroy(fsb
);
1153 ERR("Failed to allocate XACT3SoundBankImpl!\n");
1154 return E_OUTOFMEMORY
;
1157 hr
= wrapper_add_entry(This
, fsb
, &sb
->IXACT3SoundBank_iface
);
1160 FACTSoundBank_Destroy(fsb
);
1161 HeapFree(GetProcessHeap(), 0, sb
);
1165 sb
->IXACT3SoundBank_iface
.lpVtbl
= &XACT3SoundBank_Vtbl
;
1166 sb
->fact_soundbank
= fsb
;
1168 *ppSoundBank
= &sb
->IXACT3SoundBank_iface
;
1170 TRACE("Created SoundBank: %p\n", sb
);
1175 static HRESULT WINAPI
IXACT3EngineImpl_CreateInMemoryWaveBank(IXACT3Engine
*iface
,
1176 const void* pvBuffer
, DWORD dwSize
, DWORD dwFlags
,
1177 DWORD dwAllocAttributes
, IXACT3WaveBank
**ppWaveBank
)
1179 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1180 XACT3WaveBankImpl
*wb
;
1185 TRACE("(%p)->(%p, %lu, 0x%lx, 0x%lx, %p)\n", This
, pvBuffer
, dwSize
, dwFlags
,
1186 dwAllocAttributes
, ppWaveBank
);
1188 ret
= FACTAudioEngine_CreateInMemoryWaveBank(This
->fact_engine
, pvBuffer
,
1189 dwSize
, dwFlags
, dwAllocAttributes
, &fwb
);
1192 ERR("Failed to CreateWaveBank: %d\n", ret
);
1196 wb
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*wb
));
1199 FACTWaveBank_Destroy(fwb
);
1200 ERR("Failed to allocate XACT3WaveBankImpl!\n");
1201 return E_OUTOFMEMORY
;
1204 hr
= wrapper_add_entry(This
, fwb
, &wb
->IXACT3WaveBank_iface
);
1207 FACTWaveBank_Destroy(fwb
);
1208 HeapFree(GetProcessHeap(), 0, wb
);
1212 wb
->IXACT3WaveBank_iface
.lpVtbl
= &XACT3WaveBank_Vtbl
;
1213 wb
->fact_wavebank
= fwb
;
1215 *ppWaveBank
= &wb
->IXACT3WaveBank_iface
;
1217 TRACE("Created in-memory WaveBank: %p\n", wb
);
1222 static HRESULT WINAPI
IXACT3EngineImpl_CreateStreamingWaveBank(IXACT3Engine
*iface
,
1223 const XACT_WAVEBANK_STREAMING_PARAMETERS
*pParms
,
1224 IXACT3WaveBank
**ppWaveBank
)
1226 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1227 FACTStreamingParameters fakeParms
;
1228 wrap_readfile_struct
*fake
;
1229 XACT3WaveBankImpl
*wb
;
1234 TRACE("(%p)->(%p, %p)\n", This
, pParms
, ppWaveBank
);
1236 /* We have to wrap the file to fix up the callbacks! */
1237 fake
= (wrap_readfile_struct
*) CoTaskMemAlloc(
1238 sizeof(wrap_readfile_struct
));
1239 fake
->engine
= This
;
1240 fake
->file
= pParms
->file
;
1241 fakeParms
.file
= fake
;
1242 fakeParms
.flags
= pParms
->flags
;
1243 fakeParms
.offset
= pParms
->offset
;
1244 fakeParms
.packetSize
= pParms
->packetSize
;
1246 ret
= FACTAudioEngine_CreateStreamingWaveBank(This
->fact_engine
, &fakeParms
,
1250 ERR("Failed to CreateWaveBank: %d\n", ret
);
1254 wb
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*wb
));
1257 FACTWaveBank_Destroy(fwb
);
1258 ERR("Failed to allocate XACT3WaveBankImpl!\n");
1259 return E_OUTOFMEMORY
;
1262 hr
= wrapper_add_entry(This
, fwb
, &wb
->IXACT3WaveBank_iface
);
1265 FACTWaveBank_Destroy(fwb
);
1266 HeapFree(GetProcessHeap(), 0, wb
);
1270 wb
->IXACT3WaveBank_iface
.lpVtbl
= &XACT3WaveBank_Vtbl
;
1271 wb
->fact_wavebank
= fwb
;
1273 *ppWaveBank
= &wb
->IXACT3WaveBank_iface
;
1275 TRACE("Created streaming WaveBank: %p\n", wb
);
1280 #if XACT3_VER >= 0x0205
1282 static HRESULT WINAPI
IXACT3EngineImpl_PrepareInMemoryWave(IXACT3Engine
*iface
,
1283 DWORD dwFlags
, WAVEBANKENTRY entry
, DWORD
*pdwSeekTable
,
1284 BYTE
*pbWaveData
, DWORD dwPlayOffset
, XACTLOOPCOUNT nLoopCount
,
1285 IXACT3Wave
**ppWave
)
1287 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1288 FIXME("(%p): stub!\n", This
);
1292 static HRESULT WINAPI
IXACT3EngineImpl_PrepareStreamingWave(IXACT3Engine
*iface
,
1293 DWORD dwFlags
, WAVEBANKENTRY entry
,
1294 XACT_STREAMING_PARAMETERS streamingParams
, DWORD dwAlignment
,
1295 DWORD
*pdwSeekTable
, DWORD dwPlayOffset
, XACTLOOPCOUNT nLoopCount
,
1296 IXACT3Wave
**ppWave
)
1298 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1299 FIXME("(%p): stub!\n", This
);
1303 static HRESULT WINAPI
IXACT3EngineImpl_PrepareWave(IXACT3Engine
*iface
,
1304 DWORD dwFlags
, PCSTR szWavePath
, WORD wStreamingPacketSize
,
1305 DWORD dwAlignment
, DWORD dwPlayOffset
, XACTLOOPCOUNT nLoopCount
,
1306 IXACT3Wave
**ppWave
)
1308 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1309 XACT3WaveImpl
*wave
;
1310 FACTWave
*fwave
= NULL
;
1314 TRACE("(%p)->(0x%08lx, %s, %d, %ld, %ld, %d, %p)\n", This
, dwFlags
, debugstr_a(szWavePath
),
1315 wStreamingPacketSize
, dwAlignment
, dwPlayOffset
, nLoopCount
, ppWave
);
1317 ret
= FACTAudioEngine_PrepareWave(This
->fact_engine
, dwFlags
, szWavePath
, wStreamingPacketSize
,
1318 dwAlignment
, dwPlayOffset
, nLoopCount
, &fwave
);
1319 if(ret
!= 0 || !fwave
)
1321 ERR("Failed to CreateWave: %d (%p)\n", ret
, fwave
);
1325 wave
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*wave
));
1328 FACTWave_Destroy(fwave
);
1329 return E_OUTOFMEMORY
;
1332 hr
= wrapper_add_entry(This
, fwave
, &wave
->IXACT3Wave_iface
);
1335 FACTWave_Destroy(fwave
);
1336 HeapFree(GetProcessHeap(), 0, wave
);
1340 wave
->IXACT3Wave_iface
.lpVtbl
= &XACT3Wave_Vtbl
;
1341 wave
->fact_wave
= fwave
;
1342 wave
->engine
= This
;
1343 *ppWave
= &wave
->IXACT3Wave_iface
;
1345 TRACE("Created Wave: %p\n", wave
);
1353 NOTIFY_SoundBank
= 0x01,
1354 NOTIFY_WaveBank
= 0x02,
1357 NOTIFY_cueIndex
= 0x10,
1358 NOTIFY_waveIndex
= 0x20
1361 /* these constants don't have the same values across xactengine versions */
1362 static uint8_t fact_notification_type_from_xact(XACTNOTIFICATIONTYPE type
)
1364 /* we can't use a switch statement, because the constants are static const
1365 * variables, and some compilers can't deal with that */
1366 #define X(a) if (type == XACTNOTIFICATIONTYPE_##a) return FACTNOTIFICATIONTYPE_##a
1372 X(SOUNDBANKDESTROYED
);
1373 X(WAVEBANKDESTROYED
);
1374 X(LOCALVARIABLECHANGED
);
1375 X(GLOBALVARIABLECHANGED
);
1380 X(WAVEBANKPREPARED
);
1381 X(WAVEBANKSTREAMING_INVALIDCONTENT
);
1382 #if XACT3_VER >= 0x0205
1389 FIXME("unknown type %#x\n", type
);
1393 static inline void unwrap_notificationdesc(FACTNotificationDescription
*fd
,
1394 const XACT_NOTIFICATION_DESCRIPTION
*xd
)
1398 TRACE("Type %d\n", xd
->type
);
1400 memset(fd
, 0, sizeof(*fd
));
1402 fd
->type
= fact_notification_type_from_xact(xd
->type
);
1404 /* we can't use a switch statement, because the constants are static const
1405 * variables, and some compilers can't deal with that */
1407 /* Supports SoundBank, Cue index, Cue instance */
1408 if (fd
->type
== FACTNOTIFICATIONTYPE_CUEPREPARED
|| fd
->type
== FACTNOTIFICATIONTYPE_CUEPLAY
||
1409 fd
->type
== FACTNOTIFICATIONTYPE_CUESTOP
|| fd
->type
== FACTNOTIFICATIONTYPE_CUEDESTROYED
||
1410 fd
->type
== FACTNOTIFICATIONTYPE_MARKER
|| fd
->type
== FACTNOTIFICATIONTYPE_LOCALVARIABLECHANGED
)
1412 flags
= NOTIFY_SoundBank
| NOTIFY_cueIndex
| NOTIFY_Cue
;
1414 /* Supports WaveBank */
1415 else if (fd
->type
== FACTNOTIFICATIONTYPE_WAVEBANKDESTROYED
|| fd
->type
== FACTNOTIFICATIONTYPE_WAVEBANKPREPARED
||
1416 fd
->type
== FACTNOTIFICATIONTYPE_WAVEBANKSTREAMING_INVALIDCONTENT
)
1418 flags
= NOTIFY_WaveBank
;
1420 /* Supports NOTIFY_SoundBank */
1421 else if (fd
->type
== FACTNOTIFICATIONTYPE_SOUNDBANKDESTROYED
)
1423 flags
= NOTIFY_SoundBank
;
1425 /* Supports SoundBank, SoundBank, Cue index, Cue instance, WaveBank, Wave instance */
1426 else if (fd
->type
== FACTNOTIFICATIONTYPE_WAVEPLAY
|| fd
->type
== FACTNOTIFICATIONTYPE_WAVESTOP
||
1427 fd
->type
== FACTNOTIFICATIONTYPE_WAVELOOPED
)
1429 flags
= NOTIFY_SoundBank
| NOTIFY_cueIndex
| NOTIFY_Cue
| NOTIFY_WaveBank
| NOTIFY_Wave
;
1431 /* Supports WaveBank, Wave index, Wave instance */
1432 else if (fd
->type
== FACTNOTIFICATIONTYPE_WAVEPREPARED
|| fd
->type
== FACTNOTIFICATIONTYPE_WAVEDESTROYED
)
1434 flags
= NOTIFY_WaveBank
| NOTIFY_waveIndex
| NOTIFY_Wave
;
1437 /* We have to unwrap the FACT object first! */
1438 fd
->flags
= xd
->flags
;
1439 if (flags
& NOTIFY_cueIndex
)
1440 fd
->cueIndex
= xd
->cueIndex
;
1441 #if XACT3_VER >= 0x0205
1442 if (flags
& NOTIFY_waveIndex
)
1443 fd
->waveIndex
= xd
->waveIndex
;
1446 if (flags
& NOTIFY_Cue
&& xd
->pCue
!= NULL
)
1448 XACT3CueImpl
*cue
= impl_from_IXACT3Cue(xd
->pCue
);
1450 fd
->pCue
= cue
->fact_cue
;
1453 if (flags
& NOTIFY_SoundBank
&& xd
->pSoundBank
!= NULL
)
1455 XACT3SoundBankImpl
*sound
= impl_from_IXACT3SoundBank(xd
->pSoundBank
);
1457 fd
->pSoundBank
= sound
->fact_soundbank
;
1460 if (flags
& NOTIFY_WaveBank
&& xd
->pWaveBank
!= NULL
)
1462 XACT3WaveBankImpl
*bank
= impl_from_IXACT3WaveBank(xd
->pWaveBank
);
1464 fd
->pWaveBank
= bank
->fact_wavebank
;
1467 #if XACT3_VER >= 0x0205
1468 if (flags
& NOTIFY_Wave
&& xd
->pWave
!= NULL
)
1470 XACT3WaveImpl
*wave
= impl_from_IXACT3Wave(xd
->pWave
);
1472 fd
->pWave
= wave
->fact_wave
;
1477 static HRESULT WINAPI
IXACT3EngineImpl_RegisterNotification(IXACT3Engine
*iface
,
1478 const XACT_NOTIFICATION_DESCRIPTION
*pNotificationDesc
)
1480 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1481 FACTNotificationDescription fdesc
;
1483 TRACE("(%p)->(%p)\n", This
, pNotificationDesc
);
1485 if (pNotificationDesc
->type
== XACTNOTIFICATIONTYPE_WAVEBANKPREPARED
)
1486 This
->wb_prepared_context
= pNotificationDesc
->pvContext
;
1487 else if (pNotificationDesc
->type
== XACTNOTIFICATIONTYPE_WAVEBANKDESTROYED
)
1488 This
->wb_destroyed_context
= pNotificationDesc
->pvContext
;
1490 unwrap_notificationdesc(&fdesc
, pNotificationDesc
);
1491 fdesc
.pvContext
= This
;
1492 return FACTAudioEngine_RegisterNotification(This
->fact_engine
, &fdesc
);
1495 static HRESULT WINAPI
IXACT3EngineImpl_UnRegisterNotification(IXACT3Engine
*iface
,
1496 const XACT_NOTIFICATION_DESCRIPTION
*pNotificationDesc
)
1498 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1499 FACTNotificationDescription fdesc
;
1501 TRACE("(%p)->(%p)\n", This
, pNotificationDesc
);
1503 unwrap_notificationdesc(&fdesc
, pNotificationDesc
);
1504 fdesc
.pvContext
= This
;
1505 return FACTAudioEngine_UnRegisterNotification(This
->fact_engine
, &fdesc
);
1508 static XACTCATEGORY WINAPI
IXACT3EngineImpl_GetCategory(IXACT3Engine
*iface
,
1509 PCSTR szFriendlyName
)
1511 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1513 TRACE("(%p)->(%s)\n", This
, szFriendlyName
);
1515 return FACTAudioEngine_GetCategory(This
->fact_engine
, szFriendlyName
);
1518 static HRESULT WINAPI
IXACT3EngineImpl_Stop(IXACT3Engine
*iface
,
1519 XACTCATEGORY nCategory
, DWORD dwFlags
)
1521 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1523 TRACE("(%p)->(%u, 0x%lx)\n", This
, nCategory
, dwFlags
);
1525 return FACTAudioEngine_Stop(This
->fact_engine
, nCategory
, dwFlags
);
1528 static HRESULT WINAPI
IXACT3EngineImpl_SetVolume(IXACT3Engine
*iface
,
1529 XACTCATEGORY nCategory
, XACTVOLUME nVolume
)
1531 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1533 TRACE("(%p)->(%u, %f)\n", This
, nCategory
, nVolume
);
1535 return FACTAudioEngine_SetVolume(This
->fact_engine
, nCategory
, nVolume
);
1538 static HRESULT WINAPI
IXACT3EngineImpl_Pause(IXACT3Engine
*iface
,
1539 XACTCATEGORY nCategory
, BOOL fPause
)
1541 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1543 TRACE("(%p)->(%u, %u)\n", This
, nCategory
, fPause
);
1545 return FACTAudioEngine_Pause(This
->fact_engine
, nCategory
, fPause
);
1548 static XACTVARIABLEINDEX WINAPI
IXACT3EngineImpl_GetGlobalVariableIndex(
1549 IXACT3Engine
*iface
, PCSTR szFriendlyName
)
1551 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1553 TRACE("(%p)->(%s)\n", This
, szFriendlyName
);
1555 return FACTAudioEngine_GetGlobalVariableIndex(This
->fact_engine
,
1559 static HRESULT WINAPI
IXACT3EngineImpl_SetGlobalVariable(IXACT3Engine
*iface
,
1560 XACTVARIABLEINDEX nIndex
, XACTVARIABLEVALUE nValue
)
1562 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1564 TRACE("(%p)->(%u, %f)\n", This
, nIndex
, nValue
);
1566 return FACTAudioEngine_SetGlobalVariable(This
->fact_engine
, nIndex
, nValue
);
1569 static HRESULT WINAPI
IXACT3EngineImpl_GetGlobalVariable(IXACT3Engine
*iface
,
1570 XACTVARIABLEINDEX nIndex
, XACTVARIABLEVALUE
*nValue
)
1572 XACT3EngineImpl
*This
= impl_from_IXACT3Engine(iface
);
1574 TRACE("(%p)->(%u, %p)\n", This
, nIndex
, nValue
);
1576 return FACTAudioEngine_GetGlobalVariable(This
->fact_engine
, nIndex
, nValue
);
1579 static const IXACT3EngineVtbl XACT3Engine_Vtbl
=
1581 IXACT3EngineImpl_QueryInterface
,
1582 IXACT3EngineImpl_AddRef
,
1583 IXACT3EngineImpl_Release
,
1584 IXACT3EngineImpl_GetRendererCount
,
1585 IXACT3EngineImpl_GetRendererDetails
,
1586 #if XACT3_VER >= 0x0205
1587 IXACT3EngineImpl_GetFinalMixFormat
,
1589 IXACT3EngineImpl_Initialize
,
1590 IXACT3EngineImpl_ShutDown
,
1591 IXACT3EngineImpl_DoWork
,
1592 IXACT3EngineImpl_CreateSoundBank
,
1593 IXACT3EngineImpl_CreateInMemoryWaveBank
,
1594 IXACT3EngineImpl_CreateStreamingWaveBank
,
1595 #if XACT3_VER >= 0x0205
1596 IXACT3EngineImpl_PrepareWave
,
1597 IXACT3EngineImpl_PrepareInMemoryWave
,
1598 IXACT3EngineImpl_PrepareStreamingWave
,
1600 IXACT3EngineImpl_RegisterNotification
,
1601 IXACT3EngineImpl_UnRegisterNotification
,
1602 IXACT3EngineImpl_GetCategory
,
1603 IXACT3EngineImpl_Stop
,
1604 IXACT3EngineImpl_SetVolume
,
1605 IXACT3EngineImpl_Pause
,
1606 IXACT3EngineImpl_GetGlobalVariableIndex
,
1607 IXACT3EngineImpl_SetGlobalVariable
,
1608 IXACT3EngineImpl_GetGlobalVariable
1611 void* XACT_Internal_Malloc(size_t size
)
1613 return CoTaskMemAlloc(size
);
1616 void XACT_Internal_Free(void* ptr
)
1618 return CoTaskMemFree(ptr
);
1621 void* XACT_Internal_Realloc(void* ptr
, size_t size
)
1623 return CoTaskMemRealloc(ptr
, size
);
1626 static HRESULT WINAPI
XACT3CF_QueryInterface(IClassFactory
*iface
, REFIID riid
, void **ppobj
)
1628 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
1629 IsEqualGUID(riid
, &IID_IClassFactory
))
1636 WARN("(%p)->(%s, %p): interface not found\n", iface
, debugstr_guid(riid
), ppobj
);
1637 return E_NOINTERFACE
;
1640 static ULONG WINAPI
XACT3CF_AddRef(IClassFactory
*iface
)
1645 static ULONG WINAPI
XACT3CF_Release(IClassFactory
*iface
)
1650 static HRESULT WINAPI
XACT3CF_CreateInstance(IClassFactory
*iface
, IUnknown
*pOuter
,
1651 REFIID riid
, void **ppobj
)
1654 XACT3EngineImpl
*object
;
1656 TRACE("(%p)->(%p,%s,%p)\n", iface
, pOuter
, debugstr_guid(riid
), ppobj
);
1661 return CLASS_E_NOAGGREGATION
;
1663 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1665 return E_OUTOFMEMORY
;
1667 object
->IXACT3Engine_iface
.lpVtbl
= &XACT3Engine_Vtbl
;
1669 FACTCreateEngineWithCustomAllocatorEXT(
1671 &object
->fact_engine
,
1672 XACT_Internal_Malloc
,
1674 XACT_Internal_Realloc
1677 hr
= IXACT3Engine_QueryInterface(&object
->IXACT3Engine_iface
, riid
, ppobj
);
1679 HeapFree(GetProcessHeap(), 0, object
);
1683 wine_rb_init(&object
->wrapper_lookup
, wrapper_lookup_compare
);
1684 InitializeCriticalSection(&object
->wrapper_lookup_cs
);
1689 static HRESULT WINAPI
XACT3CF_LockServer(IClassFactory
*iface
, BOOL dolock
)
1691 TRACE("(%p)->(%d): stub!\n", iface
, dolock
);
1695 static const IClassFactoryVtbl XACT3CF_Vtbl
=
1697 XACT3CF_QueryInterface
,
1700 XACT3CF_CreateInstance
,
1704 static IClassFactory XACTFactory
= { &XACT3CF_Vtbl
};
1706 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD reason
, void *pReserved
)
1708 TRACE("(%p, %ld, %p)\n", hinstDLL
, reason
, pReserved
);
1712 case DLL_PROCESS_ATTACH
:
1713 DisableThreadLibraryCalls( hinstDLL
);
1714 TRACE("Using FAudio version %d\n", FAudioLinkedVersion() );
1720 HRESULT WINAPI
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, void **ppv
)
1722 if (IsEqualGUID(rclsid
, &CLSID_XACTEngine
))
1724 TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid
), debugstr_guid(riid
), ppv
);
1725 return IClassFactory_QueryInterface(&XACTFactory
, riid
, ppv
);
1728 FIXME("Unknown class %s\n", debugstr_guid(rclsid
));
1729 return CLASS_E_CLASSNOTAVAILABLE
;