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