Jump to content

Unable to use the DLL file error when executing a DLLCALL


Recommended Posts

I am working on a script that I hope expand on. Its end goal is a scaled down version of the Voicemeeter.Remote. Second benefit is to better learn DLLCalls. To say I am weak in this area is probably putting it mildly. Below is my current basic version of the script I am using to test / learn with. When the line with "VBVMR_GetParameterFloat" is executed, I get the error about being unable to use the DLL file. The other commands within the script work without error (though getting the type and version has unexpected results). I can see the API is being accessed as Voicemeeter has indicators when one is connected.

#AutoIt3Wrapper_UseX64=y

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.14.5
 Author:         myName

 Script Function:
    Template AutoIt script.

#ce ----------------------------------------------------------------------------

; Script Start - Add your code below here

#Include <array.au3>

Local $hDll = DllOpen("C:\Program Files (x86)\VB\Voicemeeter\VoicemeeterRemote64.dll")
If @error Then
    ConsoleWriteError('Error DllOpen: ' & ' Error: ' & @error & ' Extended: ' & @extended & @CR)
EndIf
$str1stat = 255

DllCall($hDll,"NONE","VBVMR_Login")
If @error Then
    ConsoleWriteError('Error VBVMR_Login: ' & ' Error: ' & @error & ' Extended: ' & @extended & @CR)
EndIf

DllCall($hDll,"NONE","VBVMR_IsParametersDirty")
If @error Then
    ConsoleWriteError('Error VBVMR_IsParametersDirty: ' & ' Error: ' & @error & ' Extended: ' & @extended & @CR)
EndIf

;~ DllCall($hDll,"STR","VBVMR_GetParameterFloat","APTR","Strip[1].A1","INT",$str1stat)
If @error Then
    ConsoleWriteError('Error VBVMR_GetParameterFloat: ' & ' Error: ' & @error & ' Extended: ' & @extended & @CR)
EndIf
;~ ConsoleWrite("Error: " & @error & " Extended: " & @extended & @CRLF)
;~ ConsoleWrite($str1stat & @CRLF)

$aVMType=DllCall($hDll,"LONG","VBVMR_GetVoicemeeterType")
If @error Then
    ConsoleWriteError('Error VBVMR_GetVoicemeeterType: ' & ' Error: ' & @error & ' Extended: ' & @extended & @CR)
EndIf
$aVMVer=DllCall($hDll,"LONG_PTR","VBVMR_GetVoicemeeterVersion")
If @error Then
    ConsoleWriteError('Error VBVMR_GetVoicemeeterVersion: ' & ' Error: ' & @error & ' Extended: ' & @extended & @CR)
EndIf

_ArrayDisplay($aVMType)
_ArrayDisplay($aVMVer)
DllCall($hDll, "NONE","VBVMR_Logout")
If @error Then
    ConsoleWriteError('Error VBVMR_Logout: ' & ' Error: ' & @error & ' Extended: ' & @extended & @CR)
EndIf

DllClose($hDll)

I have attached the current .h file for the version of Voicemeeter I am using as well. If I have tried different types (STR,INT,etc) within the DLL call. The script will either return an unknown "return type" or the DLL open will crash. (Sits for up to 30 seconds then errors). I have attempted to adopt this from other code I have seen on the internet but I suspect I just lack understanding when translating from the .h file to what is needed here.

VoicemeeterRemote.h

Link to comment
Share on other sites

I'm not familiar with C/C++ but have you tried the cdecl call convention already?

Something like:

DllCall($hDll,"NONE:cdecl","VBVMR_Login")

 

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

I did give the ":cdecl" option a try on the line in question but still received the same results..

 

; This line results in an Error code 1 even with the "cdecl" option
DllCall($hDll,"STR:cdecl","VBVMR_GetParameterFloat","APTR","Strip[1].A1","INT",$str1stat)

The other DLLCalls work without issue.

Link to comment
Share on other sites

I agree the "APTR" type is not valid. When I change to "PTR", I receive this error when attempting to run " !>18:31:08 AutoIt3.exe ended.rc:-1073741819"

As to the "Strip[1].A1" being invalid, that is how Voicemeeter references the first "control" button A1. That form of reference does work in another scripting language. I wanted to stick with AutoIt since I was a bit more familiar with it. Perhaps you can tell me what I missed to make that param incorrect? I have also modified it to "'Strip[1].A1'".

From the other scripting language, this line works" "Result := DllCall("VoicemeeterRemote64\VBVMR_GetParameterFloat", "AStr", "Strip[1].A1", "Ptr", &str1stat, "Int")"

Attached a screenshot for reference.

 

voicemeeter_screen.jpg

Link to comment
Share on other sites

This should work:

Local $aCall=DllCall($hDll,"long","VBVMR_GetParameterFloat","str","Strip[1].A1","float*",0)
Local $iParameterFloat=$aCall[2]

 

Saludos

Link to comment
Share on other sites

On 5/14/2022 at 8:23 AM, Danyfirex said:

This should work:

Local $aCall=DllCall($hDll,"long","VBVMR_GetParameterFloat","str","Strip[1].A1","float*",0)
Local $iParameterFloat=$aCall[2]

 

Saludos

This is producing much more promising results. I am able to use "_ArrayDisplay($aCall)" and see results. The status of the "A1" control isn't being displayed correctly. Looking at the other scripting tool, I see a function called "NumGet" is being used. The description of the function says "Returns the binary number stored at the specified address+offset." (ie Number := NumGet(VarOrAddress , Offset := 0, Type := "UPtr") )

I looked at the binary functions (BinaryToString) and the Binary UDF posted by @Ward in the past and either they are not what I need or I just don't understand well enough to follow.

Link to comment
Share on other sites

Link to comment
Share on other sites

1 hour ago, Danyfirex said:

what result you get and what should it be?

 

Saludos

I included a screenshot of what I see. If the A1 "control" is active, I expect to have a numeric 1 returned and likewise if it is inactive I expect a numeric 0 returned.

My code segment as it is now...
 

$aCall = DllCall($hDll,"float","VBVMR_GetParameterFloat","str","Strip[1].A1","float*",0)
If @error Then
    ConsoleWriteError('Error VBVMR_GetParameterFloat: ' & ' Error: ' & @error & ' Extended: ' & @extended & @CR)
EndIf
$iParameterFloat=$aCall[2]
MsgBox(0,"$iParameterFloa",$iParameterFloat)
_ArrayDisplay($aCall)

Thank you for assisting me... 😊

VBVMR_GetParameterFloat_ArrayDisplay.jpg

Link to comment
Share on other sites

But documentation says it returns a float:

long __stdcall VBVMR_GetParameterFloat(char * szParamName, float * pValue);

 

try this:

Local $tFloat=DllStructCreate("float value")
$aCall = DllCall($hDll,"long","VBVMR_GetParameterFloat","str","Strip[1].A1","ptr",DllStructGetPtr($tFloat))
ConsoleWrite($tFloat.value)

 

Saludos

 

Link to comment
Share on other sites

16 hours ago, Danyfirex said:

But documentation says it returns a float:

long __stdcall VBVMR_GetParameterFloat(char * szParamName, float * pValue);

 

try this:

Local $tFloat=DllStructCreate("float value")
$aCall = DllCall($hDll,"long","VBVMR_GetParameterFloat","str","Strip[1].A1","ptr",DllStructGetPtr($tFloat))
ConsoleWrite($tFloat.value)

 

Saludos

 

I agree, the .h says it returns a float. I tried your snippet of code, replacing my previous attempt. I am still seeing "0" regardless if the control is selected or not. For grins, I changed "long" to "float" to test and received the same result.

Link to comment
Share on other sites

I would like to check this deeply. PM me. I could probably get remote access and do some tests to get a solution.

 

Saludos

Link to comment
Share on other sites

I added a couple more ConsoleWrites to the code you provided yesterday. The DllStructCreate seems to be doing something... Below are 2 results, one as type "long" and the other as type "float".

As type "long"...

$aCall[0]: 0
$aCall[1]: Strip[1].A1
$aCall[2]: 0x000001F74AEA3AE0
$tFloat.value Output: 0

 

As type "float"...

$aCall[0]: 0
$aCall[1]: Strip[1].A1
$aCall[2]: 0x000001F74AEA3AE0
$tFloat.value Output: 0

 

In both instances the "A1" control is set to active.

; adapted code
Local $tFloat=DllStructCreate("float value")
$aCall = DllCall($hDll,"float","VBVMR_GetParameterFloat","str","Strip[1].A1","ptr",DllStructGetPtr($tFloat))
ConsoleWrite("$aCall[0]: " & $aCall[0] & @CRLF & "$aCall[1]: " & $aCall[1] & @CRLF & "$aCall[2]: " & $aCall[2] & @CRLF)
ConsoleWrite("$tFloat.value Output: " & $tFloat.value & @CRLF)

(Face palm moment) I suppose attaching the RemoteAPI doc might help some as well?

Link to product site: https://vb-audio.com/Voicemeeter/

VoicemeeterRemoteAPI.pdf

Link to comment
Share on other sites

Danyfirex's first suggestion for VBVMR_GetParameterFloat, where he used float* for the second parameter, works fine.  The one I use is very similar except it is set up as an API wrapper function (see below).  You keep referencing "Strip[1].A1" for the parameter.  You're aware that you are referencing the 2nd strip, not the first one, since the strip indexes starts at 0, right? (See the Input Strip Parameters section in the API PDF for details)  Could that be the reason you aren't seeing the expected value?

The image below shows the test settings on the first strip in my Voicemeeter (not Voicemeeter Banana):

image.png.d77f0de467b2e21f18f5058039922a21.png

 

When I run my script against it, using my API wrappers, I get the following info written to the console:

DllOpen successful
VBVMR_Login successful
VBVMR_IsParametersDirty     = False
VBVMR_GetVoicemeeterType    = VoiceMeeter
VBVMR_GetVoicemeeterVersion = 1.0.8.2
Strip[0].Color_y            = +0.90
Strip[0].Color_x            = -0.15
Strip[0].Mono               = 1
VBVMR_Logout executed
DllClose executed

The 3 strip parameters, in the console output above, uses the following API wrapper function in my script.  As you can see, it passes back valid float values.  For example, I used VBVMR_GetParameterFloat("Strip[0].Mono") in my test script to get the first strips Mono setting.

Func VBVMR_GetParameterFloat($sParamName)
    Local $aResult

    ;Call API
    $aResult = DllCall($ghVMDll, "long", "VBVMR_GetParameterFloat", _
                       "str"   , $sParamName, _
                       "float*", 0)
    If @error           Then Return SetError(-99, @error, -99.0)
    If $aResult[0] <> 0 Then Return SetError($aResult[0], 0, -99.0)

    Return $aResult[2]
EndFunc

This a sample of how I called the wrapper function in my test script:

;Display Strip[0].Color_y value
$sParam = "Strip[0].Color_y"
$fValue = VBVMR_GetParameterFloat($sParam)
If @error Then
    MsgBox($MB_ICONWARNING + $MB_TOPMOST, "ERROR", _
           "VBVMR_GetParameterFloat error occurred." & @LF & @LF & _
           "@error = " & @error & @LF & _
           "@extended = " & @extended)
    Exit
EndIf

ConsoleWrite(StringFormat("%-27s = %+0.2f", $sParam, $fValue) & @CRLF)

 

For the record, all of the VBVMR APIs, except 1, pass back a LONG return code.  All of the DllCalls in your original post that have "NONE" as the return code, should have "LONG".  For instance, the VBVMR_Login declaration in the header file is:

/** @name Communication Login / logout
* @{ */

	/** 
	@brief Open Communication Pipe With Voicemeeter (typically called on software startup).
	@return :	 0: OK (no error).
				 1: OK but Voicemeeter Application not launched.
				-1: cannot get client (unexpected)
				-2: unexpected login (logout was expected before).
	*/

long __stdcall VBVMR_Login(void);

So the corresponding AutoIt DllCall would be something like:

$aResult = DllCall($ghVMDll, "long", "VBVMR_Login")

If you aren't correctly defining and checking the return code after executing the API, then it is very difficult to tell if the API call was successful or not.  If it wasn't, it's the return code that will let you know why.

 

Lastly, there are several "return values" that you need to be aware of when using DllCalls.  All of them are important and, in my opinion, all should be checked.  There's @error and the array returned by the DllCall function itself.  There's the return code/value that is returned in array[0] after a successful API call, if it has a return code defined.  And there's the parameter values passed back from the API function call, if any exist.  So when you refer the return codes and values, you need to be specific as to which ones you are referring to.  Looking at some of your previous posts, you seems to be getting the return code from the API function mixed up with the parameter values that are passed back from the API call.

 

Hopefully that helps.

Edited by TheXman
Added a sample API wrapper call; Reduce image size
Link to comment
Share on other sites

Thank you @TheXman . You are right about the "Strip[1].A1". I will call it a face-palm moment. I was looking an a different script and forgot the numbering started at 0. Thank you very much for going into detail with how you use AutoIt with Voicemeeter Banana.

Using what @Danyfirex provided ( DllCall($hDll,"long","VBVMR_GetParameterFloat","str","Strip[1].A1","float*",0) ) and changing the return types to "long", I got slightly different results. For a brief bit, executing the script would return the opposite status of "A1". So if it was enabled, I would see "0", disabled showed "1". This didn't make sense to me. I rebooted my PC on the off chance the testing left things in an odd state. That did not fix it.

When I run the script after rebooting, it seems to be pot luck whether I get a correct status back. I have tried getting the state of "mono" and "B1" with minimal luck. I might get the correct state initially then after changing the setting. After that, no matter how often I change the setting or run the script, the same value is returned. For example, "A1" could be enabled but the script returns disabled. It's almost as if the DLL is not really connecting to Voicemeeter.

I have adopted your function and error checking in the hopes of getting more detail. In this case, no errors are being reported with how my script is now.

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.14.5
 Author:         myName

 Script Function:
    Template AutoIt script.

#ce ----------------------------------------------------------------------------

; Script Start - Add your code below here
#AutoIt3Wrapper_UseX64=y
#Include <array.au3>
#Include <Binary.au3>
$aCall = 0

; Open DLL
Local $hDll = DllOpen("C:\Program Files (x86)\VB\Voicemeeter\VoicemeeterRemote64.dll")
If @error Then
    ConsoleWriteError('Error DllOpen: ' & ' Error: ' & @error & ' Extended: ' & @extended & @CR)
EndIf

; Login to the DLL
$aResult = DllCall($hDll,"long","VBVMR_Login")
If @error Then
    ConsoleWriteError('Error VBVMR_Login: ' & ' Error: ' & @error & ' Extended: ' & @extended & @CR)
EndIf
;_ArrayDisplay($aResult)

; Check parameter status
$aResult = DllCall($hDll,"long","VBVMR_IsParametersDirty")
If @error Then
    ConsoleWriteError('Error VBVMR_IsParametersDirty: ' & ' Error: ' & @error & ' Extended: ' & @extended & @CR)
EndIf

; Check option status

$sParam = "Strip[1].A1"
$fValue = VBVMR_GetParameterFloat($sParam)
If @error Then
    MsgBox($MB_ICONWARNING + $MB_TOPMOST, "ERROR", _
           "VBVMR_GetParameterFloat error occurred." & @LF & @LF & _
           "@error = " & @error & @LF & _
           "@extended = " & @extended)
    Exit
EndIf
ConsoleWrite("Results: " &$sParam&" - "&$fValue&@CRLF)

; Logout of DLL
$aResult = DllCall($hDll, "long","VBVMR_Logout")
If @error Then
    ConsoleWriteError('Error VBVMR_Logout: ' & ' Error: ' & @error & ' Extended: ' & @extended & @CR)
EndIf

; Close DLL
DllClose($hDll)

Func VBVMR_GetParameterFloat($sParamName)
    Local $aResult

    ;Call API
    $aResult = DllCall($hDll, "long", "VBVMR_GetParameterFloat", _
                       "str"   , $sParamName, _
                       "float*", 0)
    If @error           Then Return SetError(-99, @error, -99.0)
    If $aResult[0] <> 0 Then Return SetError($aResult[0], 0, -99.0)

    Return $aResult[2]
EndFunc

 

Link to comment
Share on other sites

If you are making a change to Voicemeeter parameters and then rerunning the script, then that is why you are seeing odd results.  The APIs do not work that way.  The only way you will accurately see your changes running your script that way would be to change the parameters, stop & restart Voicemeeter, and then rerun your script.  If you want to be able to monitor parameter changes in real time, then you need to poll for changes by constantly checking for changes using the Is...Dirty API functions and when it is true, then do what you want to do.  I do the polling using a loop, but I guess you could also use some sort of timer-based method like AdlibRegister().   In my test script, I check for parameter changes about 10 times a second.  That seems to work fine.  The log below is an example run of a script that monitors for parameter changes using the VBVMR_IsParametersDirty() API and displays a few specific parameters whenever it detects ANY parameter change. 

In the log below, you can see that I toggle A1, Mono, and Mute in the first strip.  I then toggle them again in the same order.

2022-05-18 15:37:38   DllOpen successful
2022-05-18 15:37:38   VBVMR_Login successful
2022-05-18 15:37:38   
2022-05-18 15:37:38   Strip[0].A1    = True
2022-05-18 15:37:38   Strip[0].Mono  = True
2022-05-18 15:37:38   Strip[0].Mute  = True
2022-05-18 15:37:44   
2022-05-18 15:37:44   Strip[0].A1    = False
2022-05-18 15:37:44   Strip[0].Mono  = True
2022-05-18 15:37:44   Strip[0].Mute  = True
2022-05-18 15:37:46   
2022-05-18 15:37:46   Strip[0].A1    = False
2022-05-18 15:37:46   Strip[0].Mono  = False
2022-05-18 15:37:46   Strip[0].Mute  = True
2022-05-18 15:37:48   
2022-05-18 15:37:48   Strip[0].A1    = False
2022-05-18 15:37:48   Strip[0].Mono  = False
2022-05-18 15:37:48   Strip[0].Mute  = False
2022-05-18 15:37:50   
2022-05-18 15:37:50   Strip[0].A1    = True
2022-05-18 15:37:50   Strip[0].Mono  = False
2022-05-18 15:37:50   Strip[0].Mute  = False
2022-05-18 15:37:51   
2022-05-18 15:37:51   Strip[0].A1    = True
2022-05-18 15:37:51   Strip[0].Mono  = True
2022-05-18 15:37:51   Strip[0].Mute  = False
2022-05-18 15:37:52   
2022-05-18 15:37:52   Strip[0].A1    = True
2022-05-18 15:37:52   Strip[0].Mono  = True
2022-05-18 15:37:52   Strip[0].Mute  = True
2022-05-18 15:37:54   
2022-05-18 15:37:54   VBVMR_Logout executed
2022-05-18 15:37:54   DllClose executed

My example script is below.  Click "Reveal hidden contents" to view it.

Spoiler

This is the example script that created the log above.  It is a crude, over-simplified, example written solely to conceptually show how the Voicemeeter APIs can be implemented.  Of course there are many ways to do it.  This is just one simple example.

Note:

  • Change the $VBVMR_DIR constant to point to where your VoiceMeeter is installed.
  • The script runs continously.  Press ESC to gracefully end the script.
  • The script looks for ANY parameter changes.  When ANY parameter is changed, it will just display the value of A1, Mono, and Mute in Strip 1.  So it would be best to just modify those parameters to see them change in the log.

 

#AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d

#include <Constants.au3>

;==========================================================================
; Main Code Block
;==========================================================================
Const  $VBVMR_DIR = "C:\Program Files\VB\Voicemeeter" ; <== Modify as needed
Global $ghVMDll   = -1

;Set up hotkey to end script
HotKeySet("{ESC}", "exit_script")
MsgBox($MB_ICONINFORMATION + $MB_TOPMOST, "VMR API EXAMPLE", "Press ESC to end the script.")

;Get handle to Dll (if successful, then register func to close handle on exit)
$ghVMDll = DllOpen($VBVMR_DIR & (@AutoItX64 ? "\VoicemeeterRemote64.dll" : "\VoicemeeterRemote.dll"))
If $ghVMDll = -1 Then Exit MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", "Unable to load Voicemeeter DLL")

log_write("DllOpen successful" & @CRLF)

;Register exit routine to clean up
OnAutoItExitRegister("on_autoit_exit")

voicemeeter_api_example()

;==========================================================================
; Functions
;==========================================================================
Func voicemeeter_api_example()
    Local $sParam = ""
    Local $fValue = 0.0

    ;Login to Voicemeeter
    VBVMR_Login()
    If @error Then
        MsgBox($MB_ICONWARNING + $MB_TOPMOST, "ERROR", _
               "VBVMR_Login error occurred." & @LF & @LF & _
               "@error = " & @error & @LF & _
               "@extended = " & @extended)
        Exit
    EndIf

    log_write("VBVMR_Login successful" & @CRLF)

    ;Continously check for changes
    While 1
        If VBVMR_IsParametersDirty() Then
            log_write(@CRLF)

            ;Display Strip[0].A1 value
            $sParam = "Strip[0].A1"
            $fValue = VBVMR_GetParameterFloat($sParam)
            If @error Then
                MsgBox($MB_ICONWARNING + $MB_TOPMOST, "ERROR", _
                       "VBVMR_GetParameterFloat error occurred." & @LF & @LF & _
                       "@error = " & @error & @LF & _
                       "@extended = " & @extended)
                Exit
            EndIf
            log_write(StringFormat("%-14s = %s", $sParam, ($fValue <> 0)) & @CRLF)

            ;Display Strip[0].Mono value
            $sParam = "Strip[0].Mono"
            $fValue = VBVMR_GetParameterFloat($sParam)
            If @error Then
                MsgBox($MB_ICONWARNING + $MB_TOPMOST, "ERROR", _
                       "VBVMR_GetParameterFloat error occurred." & @LF & @LF & _
                       "@error = " & @error & @LF & _
                       "@extended = " & @extended)
                Exit
            EndIf
            log_write(StringFormat("%-14s = %s", $sParam, ($fValue <> 0)) & @CRLF)

            ;Display Strip[0].Mute value
            $sParam = "Strip[0].Mute"
            $fValue = VBVMR_GetParameterFloat($sParam)
            If @error Then
                MsgBox($MB_ICONWARNING + $MB_TOPMOST, "ERROR", _
                       "VBVMR_GetParameterFloat error occurred." & @LF & @LF & _
                       "@error = " & @error & @LF & _
                       "@extended = " & @extended)
                Exit
            EndIf
            log_write(StringFormat("%-14s = %s", $sParam, ($fValue <> 0)) & @CRLF)
        EndIf

        Sleep(100)
    WEnd
EndFunc

Func on_autoit_exit()
    log_write(@CRLF)

    ;Logout of voicemeeter
    VBVMR_Logout()
    log_write("VBVMR_Logout executed" & @CRLF)

    ;Close dll handle
    DllClose($ghVMDll)
    log_write("DllClose executed" & @CRLF)
EndFunc

Func exit_script()
    Exit
EndFunc

Func log_write($sMsg)
    Local $sDateTime = StringFormat("%s-%s-%s %02i:%02i:%02i", _
                                    @YEAR, @MON, @MDAY, @HOUR, @MIN, @SEC)

    ConsoleWrite($sDateTime & "   " & $sMsg)
EndFunc

;===============  Voicemeeter Remote API Wrappers Below  ==============

Func VBVMR_Login()
    Local $aResult

    ;Call API
    $aResult = DllCall($ghVMDll, "long", "VBVMR_Login")
    If @error           Then Return SetError(-99, @error, False)
    If $aResult[0] <> 0 Then Return SetError($aResult[0], 0, False)

    Return True
EndFunc

Func VBVMR_Logout()
    Local $aResult

    ;Call API
    $aResult = DllCall($ghVMDll, "long", "VBVMR_Logout")
    If @error           Then Return SetError(-99, @error, False)
    If $aResult[0] <> 0 Then Return SetError($aResult[0], 0, False)

    Return True
EndFunc

Func VBVMR_IsParametersDirty()
    Local $aResult

    ;Call API
    $aResult = DllCall($ghVMDll, "long", "VBVMR_IsParametersDirty")
    If @error           Then Return SetError(-99, @error, False)
    If $aResult[0] < 0  Then Return SetError($aResult[0], 0, False)

    Return ($aResult[0] ? True : False)
EndFunc

Func VBVMR_GetParameterFloat($sParamName)
    Local $aResult

    ;Call API
    $aResult = DllCall($ghVMDll, "long", "VBVMR_GetParameterFloat", _
                       "str"   , $sParamName, _
                       "float*", 0)
    If @error           Then Return SetError(-99, @error, -1.0)
    If $aResult[0] <> 0 Then Return SetError($aResult[0], 0, -1.0)

    Return $aResult[2]
EndFunc

 

 

Edited by TheXman
Link to comment
Share on other sites

@gritts

I updated my last post by adding the example script that created the log.

Link to comment
Share on other sites

After taking a look at your additional example and plinking around with my own code, I came up with the following tweak to my login function:

Func VBVMR_Login($apiDLL)
    ; Login to the DLL
    Local $aResult
    $aResult = DllCall($apiDLL, "long", "VBVMR_Login")
    If @error Then Return SetError(-99, @error, -99.0)
    If $aResult[0] <> 0 Then Return SetError($aResult[0], 0, -99.0)
    Sleep(250)
EndFunc   ;==>VBVMR_Login

Adding the Sleep function appears to have allowed the script to pause a little and then when I follow with the "VBVMR_GetParameterFloat" call, I get the values expected. I have tested this with the "A1" button and the "color" setting. Still tinkering but I suspect the more GetParamaterFloat calls I make between logout and login may require a longer sleep time. Learning as I go 😄.

You mentioned...

On 5/17/2022 at 5:56 PM, TheXman said:

For the record, all of the VBVMR APIs, except 1, pass back a LONG return code.

I attempted to pull the current version using "VBVMR_GetVoicemeeterVersion" using long as they type and "50332162" is what I get returned. I see in your example you appear to have converted the result you received into a decimal translation. Can you suggest a path I can take that might make sense? I appreciate all of the help you have provided so far and I was hoping I might figure this one out.

My end goal for all of this is 2 fold. First is to learn about handling DLL files. Second is to create a smaller GUI (if at all) version of the VM Remote. I want to be able to capture the current settings, save them along with other versions then be able to call the settings on demand. (Like one for office Teams meeting, another for personal Discord, etc)

Link to comment
Share on other sites

22 hours ago, gritts said:

I attempted to pull the current version using "VBVMR_GetVoicemeeterVersion" using long as they type and "50332162" is what I get returned.
. . .
Can you suggest a path I can take that might make sense?

Unless you were running the current version of Voicemeeter Potato at the time, I have no idea what "50332162" is or how you got it.  Since I have no intention of guessing, I would suggest that you show the code that you attempted to execute and also say which Voicemeeter product was running at the time.  With that, I can help you understand why your VBVMR_GetVoicemeeterVersion() didn't return the correct result.

If you were running your script against the current version of Voicemeeter Banana, then VBVMR_GetVoicemeeterVersion() would've returned a LONG value containing 33555970, which after decoding would be "2.0.6.2".  If you were running your script against the current version of Voicemeeter (not Voicemeeter Banana), then VBVMR_GetVoicemeeterVersion() would've returned a LONG value containing 16779266, which after decoding would be "1.0.8.2".

As it says in the header file, the version is passed back as a 32-bit (4 byte) LONG value.  To decode the version number, you get the decimal value of each of the 4 bytes.  For example, the decimal value 33555978, is 0x0200060A (big endian).  So the version number is 0x02 0x00 0x06 0x0A or v2.0.6.10 .  My VBVMR_GetVoicemeeterVersion() API wrapper achieves this by using the BinaryMid() function, but it could be done in several different ways.  Now that I've explained how to decode the LONG value into the x.x.x.x version number, why don't you try to decode 50332162 and see what you get.  :think::idea:

Edited by TheXman
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...