Modify

Opened 3 years ago

Last modified 13 months ago

#3159 assigned Bug

ObjCreateInterface and BOOL type.

Reported by: Valik Owned by: Jon
Milestone: Component: AutoIt
Version: 3.3.14.0 Severity: None
Keywords: Cc:

Description

Apologies for the large script but this is the minimum I could get it down to to demonstrate the bug.

; Interface description for IMMDeviceEnumerator.
Global Const $__Audio_CLSID_MMDeviceEnumerator = "{BCDE0395-E52F-467C-8E3D-C4579291692E}"
Global Const $__Audio_IID_IMMDeviceEnumerator = "{A95664D2-9614-4F35-A746-DE8DB63617E6}"
Global Const $__Audio_tagIMMDeviceEnumerator = "EnumAudioEndpoints hresult(dword;dword;ptr*);" & _
	"GetDefaultAudioEndpoint hresult(dword;dword;ptr*);" & _
	"GetDevice hresult(wstr;ptr*);" & _
	"RegisterEndpointNotificationCallback hresult(ptr);" & _
	"UnregisterEndpointNotificationCallback hresult(ptr);"

; Interface description for IMMDevice.
Global Const $__Audio_IID_IMMDevice = "{D666063F-1587-4E43-81F1-B948E807363F}"
Global Const $__Audio_tagIMMDevice = "Activate hresult(clsid;dword;variant*;ptr*);" & _
	"OpenPropertyStore hresult(dword;ptr*);" & _
	"GetId hresult(ptr*);" & _
	"GetState hresult(dword*);"

; Interface description for IAudioEndpointVolume
Global Const $__Audio_IID_IAudioEndpointVolume = "{5CDF2C82-841E-4546-9722-0CF74078229A}"
Global Const $__Audio_tagIAudioEndpointVolume = "RegisterControlChangeNotify hresult(ptr);" & _
	"UnregisterControlChangeNotify hresult(ptr);" & _
	"GetChannelCount hresult(UINT*);" & _
	"SetMasterVolumeLevel hresult(float;ptr);" & _
	"SetMasterVolumeLevelScalar hresult(float;ptr);" & _
	"GetMasterVolumeLevel hresult(float*);" & _
	"GetMasterVolumeLevelScalar hresult(float*);" & _
	"SetChannelVolumeLevel hresult(UINT;float;ptr);" & _
	"SetChannelVolumeLevelScalar hresult(UINT;float;ptr);" & _
	"GetChannelVolumeLevel hresult(UINT;float*);" & _
	"GetChannelVolumeLevelScalar hresult(UINT;float*);" & _
	"SetMute hresult(BOOL;ptr);" & _		; <--- This method doesn't work. Change "BOOL" to "int" and it suddenly works agian.
	"GetMute hresult(BOOL*);" & _
	"GetVolumeStepInfo hresult(UINT*;UINT*);" & _
	"VolumeStepUp hresult(ptr);" & _
	"VolumeStepDown hresult(ptr);" & _
	"QueryHardwareSupport hresult(DWORD*);" & _
	"GetVolumeRange hresult(float*;float*;float*);"

Global Const $__Audio_eRender = 0
Global Const $__Audio_eMultimedia = 1
Global Const $__AUDIO_CLSCTX_ALL = BitOR(0x1, 0x2, 0x4, 0x10)	; CLSCTX_INPROC_SERVER, CLSCTX_INPROC_HANDLER, CLSCTX_LOCAL_SERVER, CLSCTX_REMOTE_SERVER

Func Audio_GetDefaultAudioEndpoint()
	Local $oEnumerator = ObjCreateInterface($__Audio_CLSID_MMDeviceEnumerator, $__Audio_IID_IMMDeviceEnumerator, $__Audio_tagIMMDeviceEnumerator)

	Local $pEndpoint
	$oEnumerator.GetDefaultAudioEndpoint($__Audio_eRender, $__Audio_eMultimedia, $pEndpoint)
	Local $oEndpoint = ObjCreateInterface($pEndpoint, $__Audio_IID_IMMDevice, $__Audio_tagIMMDevice)

	Local $pID, $sId
	; Collect ID
	$oEndpoint.GetId($pID)
	$sId = DllStructGetData(DllStructCreate("wchar ID[" & __Audio_WinAPI_PtrStringLenW($pID) & "]", $pID), "ID")
	__Audio_WinAPI_CoTaskMemFree($pID)
	Return $sId
EndFunc	; Audio_GetDefaultAudioEndpoint()

Func Audio_SetDeviceMute($sDeviceID, $bMute)
	; Create the IMMDeviceEnumerator object.
	Local $oEnumerator = ObjCreateInterface($__Audio_CLSID_MMDeviceEnumerator, $__Audio_IID_IMMDeviceEnumerator, $__Audio_tagIMMDeviceEnumerator)

	; Get device pointer.
	Local $pDevice
	$oEnumerator.GetDevice($sDeviceID, $pDevice)

	; Convert the device pointer into an object.
	Local $oDevice = ObjCreateInterface($pDevice, $__Audio_IID_IMMDevice, $__Audio_tagIMMDevice)

	; Get the IAudioEndpointVolume pointer.
	Local $pAudioEndpointVolume
	$oDevice.Activate($__Audio_IID_IAudioEndpointVolume, $__AUDIO_CLSCTX_ALL, 0, $pAudioEndpointVolume)

	; Convert the IAudioEndpointVolume pointer into an object.
	Local $oAudioEndpointVolume = ObjCreateInterface($pAudioEndpointVolume, $__Audio_IID_IAudioEndpointVolume, $__Audio_tagIAudioEndpointVolume)

	; Set the mute state.
	$oAudioEndpointVolume.SetMute($bMute, 0)
EndFunc	; Audio_SetDeviceMute()

Func __Audio_WinAPI_CoTaskMemFree($pMem)
	DllCall("ole32.dll", "none", "CoTaskMemFree", "ptr", $pMem)
	If @error Then Return SetError(1, 0, False)
	Return True
EndFunc	; __Audio_WinAPI_CoTaskMemFree()

Func __Audio_WinAPI_PtrStringLenW($pString)
	Local $aCall = DllCall("kernel32.dll", "dword", "lstrlenW", "ptr", $pString)
	If @error Then Return SetError(1, 0, 0)
	Return $aCall[0]
EndFunc	; __Audio_WinAPI_PtrStringLenW()

Audio_SetDeviceMute(Audio_GetDefaultAudioEndpoint(), 1)

The last line is a called to Audio_SetDeviceMute() to mute the currently active audio device. The call worked fine in 3.3.8.1. With 3.3.14.0 and later (including 3.3.15.0) it doesn't work when I declare SetMute() as a BOOL:

SetMute hresult(BOOL;ptr);

If I change BOOL to int it works. It seems somewhere along the way AutoIt's conversion to BOOL in this case is failing. Passing a 0 will correctly unmute a muted device. Passing a 1 (the value of TRUE in the Windows SDK) fails.

To reiterate, this is a regression. It used to work fine. With the latest versions of AutoIt, it does not. Unfortunately I jumped straight from 3.3.8.1 to 3.3.14.0 so if it broke somewhere earlier I missed the exact build. I'm running Windows 10 x64 but this isn't OS specific.

Attachments (0)

Change History (1)

comment:1 Changed 13 months ago by Jpm

  • Owner set to Jon
  • Status changed from new to assigned

Guidelines for posting comments:

  • You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
  • In-depth discussions should take place on the forum.

For more information see the full version of the ticket guidelines here.

Add Comment

Modify Ticket

Action
as assigned The owner will remain Jon.
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.