https://learn.microsoft.com/en-us/windo ... rfaceasync
and a Microsoft sample here
https://learn.microsoft.com/en-us/sampl ... io-sample/
I have already done this in dotnet but i would love to get this going in PB. At the moment it unexpectedly quits without much to go on. I have a feeling the ActivateAudioInterfaceAsync parameter declaration may be wrong. Any help would be much appreciated.
Code: Select all
Global ActivateAudioInterfaceAsync
Prototype.i ActivateAudioInterfaceAsync(deviceInterfacePath.p-unicode, *riid, *activationParams, *completionHandler, *activationOperation)
If OpenLibrary(0, "Mmdevapi.dll")
ActivateAudioInterfaceAsync.ActivateAudioInterfaceAsync = GetFunction(0, "ActivateAudioInterfaceAsync")
;CloseLibrary(0)
EndIf
; -----------------------------------------------------------------------------
; COM Interfaces
; -----------------------------------------------------------------------------
Interface IActivateAudioInterfaceAsyncOperation Extends IUnknown
GetActivateResult(*activateResult, *activatedInterface)
EndInterface
Interface IActivateAudioInterfaceCompletionHandler Extends IUnknown
ActivateCompleted(*activateOperation)
EndInterface
; Enumerations
Enumeration; AUDIOCLIENT_ACTIVATION_TYPE
#AUDIOCLIENT_ACTIVATION_TYPE_DEFAULT
#AUDIOCLIENT_ACTIVATION_TYPE_PROCESS_LOOPBACK
EndEnumeration
Enumeration; PROCESS_LOOPBACK_MODE
#PROCESS_LOOPBACK_MODE_INCLUDE_TARGET_PROCESS_TREE
#PROCESS_LOOPBACK_MODE_EXCLUDE_TARGET_PROCESS_TREE
EndEnumeration
; Structures
Structure AUDIOCLIENT_PROCESS_LOOPBACK_PARAMS Align #PB_Structure_AlignC
TargetProcessId.l ; DWORD (32-bit integer)
ProcessLoopbackMode.l ; PROCESS_LOOPBACK_MODE enumeration
EndStructure
; Main structure
Structure AUDIOCLIENT_ACTIVATION_PARAMS Align #PB_Structure_AlignC
ActivationType.l ; AUDIOCLIENT_ACTIVATION_TYPE enumeration
ProcessLoopbackParams.AUDIOCLIENT_PROCESS_LOOPBACK_PARAMS
EndStructure
; COM object structure.
Structure MyAudioSessionNotificationObj
lpVtbl.i ; Pointer to vtable
RefCount.l ; Reference counter
EndStructure
; Global pointer to the shared vtable
Global *MyAudioSessionNotificationVTable = #Null
Procedure MyAddRef(*Object)
Protected newCount = PeekL(*Object + SizeOf(Quad)) + 1
PokeL(*Object + SizeOf(Quad), newCount)
ProcedureReturn newCount
EndProcedure
Procedure MyQueryInterface(*Object, riid.i, ppvObject.i)
PokeD(ppvObject, *Object)
MyAddRef(*Object)
ProcedureReturn #S_OK
EndProcedure
Procedure MyRelease(*Object)
Protected newCount = PeekL(*Object + SizeOf(Quad)) - 1
PokeL(*Object + SizeOf(Quad), newCount)
If newCount = 0
FreeMemory(*Object)
EndIf
ProcedureReturn newCount
EndProcedure
Procedure MyActivateCompleted(*Object, *asyncOp.IActivateAudioInterfaceAsyncOperation)
Protected activateResult, activatedInterface
*asyncOp\GetActivateResult(@activateResult, @activatedInterface)
If activateResult = #S_OK
Debug "Activation succeeded!"
; use activatedInterface here (cast to IAudioClient)
Else
Debug "Activation failed: " + Hex(activateResult)
EndIf
;asyncOp\Release()
ProcedureReturn #S_OK
EndProcedure
Procedure CreateMyAudioSessionNotification()
Protected *pObj = AllocateMemory(SizeOf(MyAudioSessionNotificationObj))
If *pObj = 0
ProcedureReturn #Null
EndIf
If *MyAudioSessionNotificationVTable = #Null
*MyAudioSessionNotificationVTable = AllocateMemory(4 * SizeOf(Quad))
If *MyAudioSessionNotificationVTable = #Null
FreeMemory(*pObj)
ProcedureReturn #Null
EndIf
PokeI(*MyAudioSessionNotificationVTable + 0 * SizeOf(Quad), @MyQueryInterface())
PokeI(*MyAudioSessionNotificationVTable + 1 * SizeOf(Quad), @MyAddRef())
PokeI(*MyAudioSessionNotificationVTable + 2 * SizeOf(Quad), @MyRelease())
PokeI(*MyAudioSessionNotificationVTable + 3 * SizeOf(Quad), @MyActivateCompleted())
EndIf
PokeI(*pObj, *MyAudioSessionNotificationVTable)
PokeL(*pObj + SizeOf(Quad), 1)
ProcedureReturn *pObj
EndProcedure
Structure BlobData
cbSize.l
*pBlobData
EndStructure
Structure PropVariant
vt.w
wReserved1.w
wReserved2.w
wReserved3.w
blob.BlobData
EndStructure
Global asyncOp.IActivateAudioInterfaceAsyncOperation
Global MyAudioSessionNotification.IActivateAudioInterfaceCompletionHandler
Procedure MTAThread(val)
hr = CoInitializeEx_(#Null, #COINIT_MULTITHREADED)
If hr <> #S_OK
Debug "CoInitialize_ failed, hr=" + Hex(hr)
End
EndIf
VIRTUAL_AUDIO_DEVICE_PROCESS_LOOPBACK.s = "VAD\Process_Loopback"
audioclientActivationParams.AUDIOCLIENT_ACTIVATION_PARAMS
audioclientActivationParams\ProcessLoopbackParams\ProcessLoopbackMode = #PROCESS_LOOPBACK_MODE_INCLUDE_TARGET_PROCESS_TREE
audioclientActivationParams\ProcessLoopbackParams\TargetProcessId = 27336
audioclientActivationParams\ActivationType = #AUDIOCLIENT_ACTIVATION_TYPE_PROCESS_LOOPBACK
activateParams.PropVariant
activateParams\vt = 65; VT_BLOB
activateParams\blob\cbSize = SizeOf(audioclientActivationParams)
activateParams\blob\pBlobData = audioclientActivationParams
MyAudioSessionNotification = CreateMyAudioSessionNotification()
hr = ActivateAudioInterfaceAsync(VIRTUAL_AUDIO_DEVICE_PROCESS_LOOPBACK, ?IID_IAudioClient, PropVariant, MyAudioSessionNotification, @asyncOp)
If hr <> #S_OK
Debug "ActivateAudioInterfaceAsync() failed hr=" + Hex(hr)
End
EndIf
EndProcedure
CreateThread(@MTAThread(), 0)
Repeat
Delay(1000)
ForEver
DataSection
IID_IAudioClient:
Data.l $1CB9AD4C
Data.w $DBFA,$4C32
Data.b $B1,$78,$C2,$F5,$68,$A7,$03,$B2
EndDataSectionCode: Select all
"VAD\\Process_Loopback"Code: Select all
"VAD\Process_Loopback"Code: Select all
Define asyncOp.IActivateAudioInterfaceAsyncOperation
Define MyAudioSessionNotification.IActivateAudioInterfaceCompletionHandler*EDIT*
Modified to run in an MTA thread.
Solved thanks to mk-soft and Justin.
https://www.purebasic.fr/english/viewtopic.php?t=86273


