xactengine3_7: Map IXACT3Wave interfaces.
[wine.git] / dlls / xactengine3_7 / xact_dll.c
blob13a6133bb95893f003bdd3927a198c0aab4403e1
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(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
54 #endif
56 struct wrapper_lookup
58 struct wine_rb_entry entry;
59 void *fact;
60 void *xact;
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;
76 } XACT3EngineImpl;
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);
100 if (!entry)
102 LeaveCriticalSection(&engine->wrapper_lookup_cs);
104 WARN("cannot find key in wrapper lookup\n");
106 else
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;
120 UINT ret;
122 lookup = HeapAlloc(GetProcessHeap(), 0, sizeof(*lookup));
123 if (!lookup)
125 ERR("Failed to allocate wrapper_lookup!\n");
126 return E_OUTOFMEMORY;
128 lookup->fact = fact;
129 lookup->xact = xact;
131 EnterCriticalSection(&engine->wrapper_lookup_cs);
132 ret = wine_rb_put(&engine->wrapper_lookup, lookup->fact, &lookup->entry);
133 LeaveCriticalSection(&engine->wrapper_lookup_cs);
135 if (ret)
137 WARN("wrapper_lookup already present in the tree??\n");
138 HeapFree(GetProcessHeap(), 0, lookup);
141 return S_OK;
144 typedef struct _XACT3CueImpl {
145 IXACT3Cue IXACT3Cue_iface;
146 FACTCue *fact_cue;
147 XACT3EngineImpl *engine;
148 } XACT3CueImpl;
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);
185 UINT ret;
187 TRACE("(%p)\n", iface);
189 ret = FACTCue_Destroy(This->fact_cue);
190 if (ret != 0)
191 WARN("FACTCue_Destroy returned %d\n", ret);
192 wrapper_remove_entry(This->engine, This->fact_cue);
193 HeapFree(GetProcessHeap(), 0, This);
194 return S_OK;
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);
204 return E_NOTIMPL;
207 static HRESULT WINAPI IXACT3CueImpl_SetChannelMap(IXACT3Cue *iface, XACTCHANNELMAP *map)
209 FIXME("(%p)->(%p)\n", iface, map);
211 return E_NOTIMPL;
214 static HRESULT WINAPI IXACT3CueImpl_GetChannelVolume(IXACT3Cue *iface, XACTCHANNELVOLUME *volume)
216 FIXME("(%p)->(%p)\n", iface, volume);
218 return E_NOTIMPL;
221 static HRESULT WINAPI IXACT3CueImpl_SetChannelVolume(IXACT3Cue *iface, XACTCHANNELVOLUME *volume)
223 FIXME("(%p)->(%p)\n", iface, volume);
225 return E_NOTIMPL;
228 #endif
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;
288 HRESULT hr;
290 TRACE("(%p)->(%p)\n", iface, ppProperties);
292 hr = FACTCue_GetProperties(This->fact_cue, &fProps);
293 if(FAILED(hr))
294 return hr;
296 *ppProperties = (XACT_CUE_INSTANCE_PROPERTIES*) fProps;
297 return hr;
299 #endif
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);
307 return S_OK;
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);
317 return S_OK;
319 #endif
321 static const IXACT3CueVtbl XACT3Cue_Vtbl =
323 IXACT3CueImpl_Play,
324 IXACT3CueImpl_Stop,
325 IXACT3CueImpl_GetState,
326 IXACT3CueImpl_Destroy,
327 #if XACT3_VER < 0x0300
328 IXACT3CueImpl_GetChannelMap,
329 IXACT3CueImpl_SetChannelMap,
330 IXACT3CueImpl_GetChannelVolume,
331 IXACT3CueImpl_SetChannelVolume,
332 #endif
333 IXACT3CueImpl_SetMatrixCoefficients,
334 IXACT3CueImpl_GetVariableIndex,
335 IXACT3CueImpl_SetVariable,
336 IXACT3CueImpl_GetVariable,
337 IXACT3CueImpl_Pause,
338 #if XACT3_VER >= 0x0205
339 IXACT3CueImpl_GetProperties,
340 #endif
341 #if XACT3_VER >= 0x0300
342 IXACT3CueImpl_SetOutputVoices,
343 IXACT3CueImpl_SetOutputVoiceMatrix
344 #endif
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);
390 #endif
392 static HRESULT WINAPI IXACT3SoundBankImpl_Prepare(IXACT3SoundBank *iface,
393 XACTINDEX nCueIndex, DWORD dwFlags, XACTTIME timeOffset,
394 IXACT3Cue** ppCue)
396 XACT3SoundBankImpl *This = impl_from_IXACT3SoundBank(iface);
397 XACT3CueImpl *cue;
398 FACTCue *fcue;
399 UINT ret;
400 HRESULT hr;
402 TRACE("(%p)->(%u, 0x%lx, %lu, %p)\n", This, nCueIndex, dwFlags, timeOffset,
403 ppCue);
405 ret = FACTSoundBank_Prepare(This->fact_soundbank, nCueIndex, dwFlags,
406 timeOffset, &fcue);
407 if(ret != 0)
409 ERR("Failed to CreateCue: %d\n", ret);
410 return E_FAIL;
413 cue = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cue));
414 if (!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);
422 if (FAILED(hr))
424 FACTCue_Destroy(fcue);
425 HeapFree(GetProcessHeap(), 0, cue);
426 return hr;
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);
436 return S_OK;
439 static HRESULT WINAPI IXACT3SoundBankImpl_Play(IXACT3SoundBank *iface,
440 XACTINDEX nCueIndex, DWORD dwFlags, XACTTIME timeOffset,
441 IXACT3Cue** ppCue)
443 XACT3SoundBankImpl *This = impl_from_IXACT3SoundBank(iface);
444 XACT3CueImpl *cue;
445 FACTCue *fcue;
446 HRESULT hr;
448 TRACE("(%p)->(%u, 0x%lx, %lu, %p)\n", This, nCueIndex, dwFlags, timeOffset,
449 ppCue);
451 /* If the application doesn't want a handle, don't generate one at all.
452 * Let the engine handle that memory instead.
453 * -flibit
455 if (ppCue == NULL){
456 hr = FACTSoundBank_Play(This->fact_soundbank, nCueIndex, dwFlags,
457 timeOffset, NULL);
458 }else{
459 hr = FACTSoundBank_Play(This->fact_soundbank, nCueIndex, dwFlags,
460 timeOffset, &fcue);
461 if(FAILED(hr))
462 return hr;
464 cue = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cue));
465 if (!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);
473 if (FAILED(hr))
475 FACTCue_Destroy(fcue);
476 HeapFree(GetProcessHeap(), 0, cue);
477 return hr;
480 cue->IXACT3Cue_iface.lpVtbl = &XACT3Cue_Vtbl;
481 cue->fact_cue = fcue;
482 cue->engine = This->engine;
483 *ppCue = &cue->IXACT3Cue_iface;
486 return hr;
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);
502 HRESULT hr;
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);
510 return hr;
513 static HRESULT WINAPI IXACT3SoundBankImpl_GetState(IXACT3SoundBank *iface,
514 DWORD *pdwState)
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,
529 #endif
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;
542 FACTWave *fact_wave;
543 XACT3EngineImpl *engine;
544 } XACT3WaveImpl;
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);
554 HRESULT hr;
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);
561 return hr;
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,
645 IXACT3WaveImpl_Play,
646 IXACT3WaveImpl_Stop,
647 IXACT3WaveImpl_Pause,
648 IXACT3WaveImpl_GetState,
649 IXACT3WaveImpl_SetPitch,
650 IXACT3WaveImpl_SetVolume,
651 IXACT3WaveImpl_SetMatrixCoefficients,
652 IXACT3WaveImpl_GetProperties
655 #endif
657 typedef struct _XACT3WaveBankImpl {
658 IXACT3WaveBank IXACT3WaveBank_iface;
660 FACTWaveBank *fact_wavebank;
661 struct _XACT3EngineImpl *engine;
662 } XACT3WaveBankImpl;
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);
672 HRESULT hr;
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);
681 return hr;
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);
722 XACT3WaveImpl *wave;
723 FACTWave *fwave;
724 UINT ret;
725 HRESULT hr;
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);
732 if(ret != 0)
734 ERR("Failed to CreateWave: %d\n", ret);
735 return E_FAIL;
738 wave = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wave));
739 if (!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);
747 if (FAILED(hr))
749 FACTWave_Destroy(fwave);
750 HeapFree(GetProcessHeap(), 0, wave);
751 return hr;
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);
761 return S_OK;
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);
769 XACT3WaveImpl *wave;
770 FACTWave *fwave;
771 HRESULT hr;
773 TRACE("(%p)->(0x%x, %lu, 0x%lx, %u, %p)\n", This, nWaveIndex, dwFlags, dwPlayOffset,
774 nLoopCount, ppWave);
776 /* If the application doesn't want a handle, don't generate one at all.
777 * Let the engine handle that memory instead.
778 * -flibit
780 if (ppWave == NULL){
781 hr = FACTWaveBank_Play(This->fact_wavebank, nWaveIndex, dwFlags,
782 dwPlayOffset, nLoopCount, NULL);
783 }else{
784 hr = FACTWaveBank_Play(This->fact_wavebank, nWaveIndex, dwFlags,
785 dwPlayOffset, nLoopCount, &fwave);
786 if(FAILED(hr))
787 return hr;
789 wave = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wave));
790 if (!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);
798 if (FAILED(hr))
800 FACTWave_Destroy(fwave);
801 HeapFree(GetProcessHeap(), 0, wave);
802 return hr;
805 wave->IXACT3Wave_iface.lpVtbl = &XACT3Wave_Vtbl;
806 wave->fact_wave = fwave;
807 wave->engine = This->engine;
808 *ppWave = &wave->IXACT3Wave_iface;
811 return hr;
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);
824 #endif
826 static HRESULT WINAPI IXACT3WaveBankImpl_GetState(IXACT3WaveBank *iface,
827 DWORD *pdwState)
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,
846 #endif
847 IXACT3WaveBankImpl_GetState
850 typedef struct wrap_readfile_struct {
851 XACT3EngineImpl *engine;
852 HANDLE file;
853 } wrap_readfile_struct;
855 static int32_t FACTCALL wrap_readfile(
856 void* hFile,
857 void* lpBuffer,
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(
868 void* hFile,
869 FACTOverlapped *lpOverlapped,
870 uint32_t *lpNumberOfBytesTransferred,
871 int32_t bWait)
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;
894 else
895 *ppvObject = NULL;
897 if (*ppvObject){
898 IUnknown_AddRef((IUnknown*)*ppvObject);
899 return S_OK;
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);
912 return 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);
922 if (!ref)
924 DeleteCriticalSection(&This->wrapper_lookup_cs);
925 wine_rb_destroy(&This->wrapper_lookup, wrapper_lookup_destroy, NULL);
926 HeapFree(GetProcessHeap(), 0, This);
928 return ref;
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);
965 #endif
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
972 X(CUEPREPARED);
973 X(CUEPLAY);
974 X(CUESTOP);
975 X(CUEDESTROYED);
976 X(MARKER);
977 X(SOUNDBANKDESTROYED);
978 X(WAVEBANKDESTROYED);
979 X(LOCALVARIABLECHANGED);
980 X(GLOBALVARIABLECHANGED);
981 X(GUICONNECTED);
982 X(GUIDISCONNECTED);
983 X(WAVEPLAY);
984 X(WAVESTOP);
985 X(WAVEBANKPREPARED);
986 X(WAVEBANKSTREAMING_INVALIDCONTENT);
987 #if XACT3_VER >= 0x0205
988 X(WAVEPREPARED);
989 X(WAVELOOPED);
990 X(WAVEDESTROYED);
991 #endif
992 #undef X
994 FIXME("unknown type %#x\n", type);
995 return 0;
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 */
1008 if (!engine)
1010 WARN("Notification context is NULL\n");
1011 return;
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);
1022 if (!entry)
1024 WARN("cannot find wave bank in wrapper lookup\n");
1025 xnotification.waveBank.pWaveBank = NULL;
1027 else
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;
1035 else
1036 xnotification.pvContext = engine->wb_destroyed_context;
1038 else
1040 FIXME("Unsupported callback type %d\n", notification->type);
1041 return;
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;
1052 UINT ret;
1054 TRACE("(%p)->(%p)\n", This, pParams);
1056 memset(&params, 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.
1076 * -flibit
1078 if (pParams->pXAudio2 != NULL){
1079 FIXME("pXAudio2 parameter not supported!\n");
1081 if (pParams->pMasteringVoice != NULL){
1082 FIXME("pMasteringVoice parameter not supported!\n");
1085 #endif
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, &params);
1104 if (ret != 0)
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;
1134 FACTSoundBank *fsb;
1135 UINT ret;
1136 HRESULT hr;
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);
1143 if(ret != 0)
1145 ERR("Failed to CreateSoundBank: %d\n", ret);
1146 return E_FAIL;
1149 sb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*sb));
1150 if (!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);
1158 if (FAILED(hr))
1160 FACTSoundBank_Destroy(fsb);
1161 HeapFree(GetProcessHeap(), 0, sb);
1162 return hr;
1165 sb->IXACT3SoundBank_iface.lpVtbl = &XACT3SoundBank_Vtbl;
1166 sb->fact_soundbank = fsb;
1167 sb->engine = This;
1168 *ppSoundBank = &sb->IXACT3SoundBank_iface;
1170 TRACE("Created SoundBank: %p\n", sb);
1172 return S_OK;
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;
1181 FACTWaveBank *fwb;
1182 HRESULT hr;
1183 UINT ret;
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);
1190 if(ret != 0)
1192 ERR("Failed to CreateWaveBank: %d\n", ret);
1193 return E_FAIL;
1196 wb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wb));
1197 if (!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);
1205 if (FAILED(hr))
1207 FACTWaveBank_Destroy(fwb);
1208 HeapFree(GetProcessHeap(), 0, wb);
1209 return hr;
1212 wb->IXACT3WaveBank_iface.lpVtbl = &XACT3WaveBank_Vtbl;
1213 wb->fact_wavebank = fwb;
1214 wb->engine = This;
1215 *ppWaveBank = &wb->IXACT3WaveBank_iface;
1217 TRACE("Created in-memory WaveBank: %p\n", wb);
1219 return S_OK;
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;
1230 FACTWaveBank *fwb;
1231 UINT ret;
1232 HRESULT hr;
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,
1247 &fwb);
1248 if(ret != 0)
1250 ERR("Failed to CreateWaveBank: %d\n", ret);
1251 return E_FAIL;
1254 wb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wb));
1255 if (!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);
1263 if (FAILED(hr))
1265 FACTWaveBank_Destroy(fwb);
1266 HeapFree(GetProcessHeap(), 0, wb);
1267 return hr;
1270 wb->IXACT3WaveBank_iface.lpVtbl = &XACT3WaveBank_Vtbl;
1271 wb->fact_wavebank = fwb;
1272 wb->engine = This;
1273 *ppWaveBank = &wb->IXACT3WaveBank_iface;
1275 TRACE("Created streaming WaveBank: %p\n", wb);
1277 return S_OK;
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);
1289 return E_NOTIMPL;
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);
1300 return E_NOTIMPL;
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;
1311 UINT ret;
1312 HRESULT hr;
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);
1322 return E_FAIL;
1325 wave = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wave));
1326 if (!wave)
1328 FACTWave_Destroy(fwave);
1329 return E_OUTOFMEMORY;
1332 hr = wrapper_add_entry(This, fwave, &wave->IXACT3Wave_iface);
1333 if (FAILED(hr))
1335 FACTWave_Destroy(fwave);
1336 HeapFree(GetProcessHeap(), 0, wave);
1337 return hr;
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);
1347 return S_OK;
1350 #endif
1352 enum {
1353 NOTIFY_SoundBank = 0x01,
1354 NOTIFY_WaveBank = 0x02,
1355 NOTIFY_Cue = 0x04,
1356 NOTIFY_Wave = 0x08,
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
1367 X(CUEPREPARED);
1368 X(CUEPLAY);
1369 X(CUESTOP);
1370 X(CUEDESTROYED);
1371 X(MARKER);
1372 X(SOUNDBANKDESTROYED);
1373 X(WAVEBANKDESTROYED);
1374 X(LOCALVARIABLECHANGED);
1375 X(GLOBALVARIABLECHANGED);
1376 X(GUICONNECTED);
1377 X(GUIDISCONNECTED);
1378 X(WAVEPLAY);
1379 X(WAVESTOP);
1380 X(WAVEBANKPREPARED);
1381 X(WAVEBANKSTREAMING_INVALIDCONTENT);
1382 #if XACT3_VER >= 0x0205
1383 X(WAVEPREPARED);
1384 X(WAVELOOPED);
1385 X(WAVEDESTROYED);
1386 #endif
1387 #undef X
1389 FIXME("unknown type %#x\n", type);
1390 return 0;
1393 static inline void unwrap_notificationdesc(FACTNotificationDescription *fd,
1394 const XACT_NOTIFICATION_DESCRIPTION *xd)
1396 DWORD flags = 0;
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;
1444 #endif
1446 if (flags & NOTIFY_Cue && xd->pCue != NULL)
1448 XACT3CueImpl *cue = impl_from_IXACT3Cue(xd->pCue);
1449 if (cue)
1450 fd->pCue = cue->fact_cue;
1453 if (flags & NOTIFY_SoundBank && xd->pSoundBank != NULL)
1455 XACT3SoundBankImpl *sound = impl_from_IXACT3SoundBank(xd->pSoundBank);
1456 if (sound)
1457 fd->pSoundBank = sound->fact_soundbank;
1460 if (flags & NOTIFY_WaveBank && xd->pWaveBank != NULL)
1462 XACT3WaveBankImpl *bank = impl_from_IXACT3WaveBank(xd->pWaveBank);
1463 if (bank)
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);
1471 if (wave)
1472 fd->pWave = wave->fact_wave;
1474 #endif
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,
1556 szFriendlyName);
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,
1588 #endif
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,
1599 #endif
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))
1631 *ppobj = iface;
1632 return S_OK;
1635 *ppobj = NULL;
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)
1642 return 2;
1645 static ULONG WINAPI XACT3CF_Release(IClassFactory *iface)
1647 return 1;
1650 static HRESULT WINAPI XACT3CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
1651 REFIID riid, void **ppobj)
1653 HRESULT hr;
1654 XACT3EngineImpl *object;
1656 TRACE("(%p)->(%p,%s,%p)\n", iface, pOuter, debugstr_guid(riid), ppobj);
1658 *ppobj = NULL;
1660 if(pOuter)
1661 return CLASS_E_NOAGGREGATION;
1663 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1664 if(!object)
1665 return E_OUTOFMEMORY;
1667 object->IXACT3Engine_iface.lpVtbl = &XACT3Engine_Vtbl;
1669 FACTCreateEngineWithCustomAllocatorEXT(
1671 &object->fact_engine,
1672 XACT_Internal_Malloc,
1673 XACT_Internal_Free,
1674 XACT_Internal_Realloc
1677 hr = IXACT3Engine_QueryInterface(&object->IXACT3Engine_iface, riid, ppobj);
1678 if(FAILED(hr)){
1679 HeapFree(GetProcessHeap(), 0, object);
1680 return hr;
1683 wine_rb_init(&object->wrapper_lookup, wrapper_lookup_compare);
1684 InitializeCriticalSection(&object->wrapper_lookup_cs);
1686 return hr;
1689 static HRESULT WINAPI XACT3CF_LockServer(IClassFactory *iface, BOOL dolock)
1691 TRACE("(%p)->(%d): stub!\n", iface, dolock);
1692 return S_OK;
1695 static const IClassFactoryVtbl XACT3CF_Vtbl =
1697 XACT3CF_QueryInterface,
1698 XACT3CF_AddRef,
1699 XACT3CF_Release,
1700 XACT3CF_CreateInstance,
1701 XACT3CF_LockServer
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);
1710 switch (reason)
1712 case DLL_PROCESS_ATTACH:
1713 DisableThreadLibraryCalls( hinstDLL );
1714 TRACE("Using FAudio version %d\n", FAudioLinkedVersion() );
1715 break;
1717 return TRUE;
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;