Read data from DLL Function

I can’t read the data returned by the function.
Normally the parameters of the function are byref by default and therefore the parameters are shared.

Why this sample doesn’t work ?

Declare Function mciSendString lib “winmm.dll” Alias “mciSendStringA” (lpstrCommand as Cstring, lpstrReturnString as CString, uReturnLength as Integer, hwndCallback as Integer) as Integer

Dim Position as Cstring

Dim Result as Integer = mciSendString("status "+“AAA position” , Position, 100, 0)
’ Result returns the correct value => Command is valid

'Position value return “”
Return Position

What DLL?
Show code on how you called DLL

Hi @Sacha_Donati,

My mciSendString is almost the same as yours. Here is the method that I have (Chapter 16, Example 16-1 in the Windows Declare book):

Public Function mciSendString(lpszCommand as String, lpszReturnString as String, cchReturn as UInt32, hWndCallback as Integer) as Integer
  #If TargetWindows
    Declare Function mciSendStringW lib "Winmm.dll" (lpszCommand as Wstring, _
    lpszReturnString as WString, cchReturn as UInt32, hWndCallback as Integer) as Integer
    Declare Function mciSendStringA lib "Winmm.dll" (lpszCommand as Cstring, _
    lpszReturnString as CString, cchReturn as UInt32, hWndCallback as Integer) as Integer
    If System.IsFunctionAvailable("mciSendStringW","Winmm.dll") Then
      Return mciSendStringW(lpszCommand, lpszReturnString, cchReturn, hWndCallback)
    Else
      Return mciSendStringA(lpszCommand, lpszReturnString, cchReturn, hWndCallback)
    End If
  #Else
    //System.DebugLog "This is not a Windows OS"
    Return 0
  #Endif
End Function
1 Like

Hi Eugene,
Your sample returns an integer (Error number) but i need the value from lpszReturnString

The following link shows how to read location data in VB.

https://www.vbforums.com/showthread.php?640158-volume-and-position-in-multimedia-control

I tried to convert the command from VB to Xojo but it doesn’t work.

Note: The others commands like play - stop… works fine

Sloppy code, just for proof of concept, works for me in 64bit, memoryblock used so you dont have to prespace a wstring for the return:

'if low is 268 on any call, the memoryblock isnt large enough, needs code to cope with that

'if low is 277 on open, its probably that your codec is 32/64bit (depending on what you're building for)
'64bit works for me, 32bit doesn't, probably due to the codec, not double chceked

Declare Function mciSendStringW Lib "winmm" (command As WString, buffer As Ptr, bufferSize As UInt32, hwndCallback As Integer) As UInt32

Dim high As UInt16 
Dim low As UInt16 
Dim ok As UInt32

Dim mb As New MemoryBlock(128)
ok = mciSendStringW("open ""C:\Users\Julian\Videos\2023-03-28 17-24-02-output.mp4"" type mpegvideo alias filealias", mb, mb.Size / 2, 0) 'size is halfed as windows uses utf16

high = Bitwise.ShiftRight(ok, 16)
low = Bitwise.BitAnd(ok, &hFFFF)
System.DebugLog("high=" + high.ToString())
System.DebugLog("low=" + low.ToString())

ok = mciSendStringW("status filealias length", mb, mb.Size / 2, 0) 'size is halfed as windows uses utf16
Dim s As String = mb.WString(0).DefineEncoding(Encodings.UTF16)

System.DebugLog("length=" + s)

high = Bitwise.ShiftRight(ok, 16)
low = Bitwise.BitAnd(ok, &hFFFF)
System.DebugLog("high=" + high.ToString())
System.DebugLog("low=" + low.ToString())
1 Like

I figured it out, although I still need to make the code a little cleaner. I will make updates in the Delcare book and send it out to subscribers when updates are complete during my ‘free’ time :rofl: … Here are the steps to get you going.

First, open the mp3 file with this code:

Sub Action() Handles Action
  Var RetVal as Integer //Returned value or error
  Var SoundType as String //used by Windows player
  Var FileExtension as String = ExtensionName(TFShellPath.Value) //determine file format
  
  //Determine file extension and assign SoundType
  //There is a long list, and only a few are shown
  //Add more file extensions and sound types here
  If FileExtension = "mp3" Then 
    SoundType = "MPEGVideo"
  ElseIf FileExtension = "avi" Then 
    SoundType = "MPEGVideo"
  ElseIf FileExtension = "wav" Then 
    SoundType = "Waveaudio"
  ElseIf FileExtension = "mid" Then 
    SoundType = "Sequencer"
  Else
    MessageDialog.Show ("Sound type not supported. Try another sound extension.")
    Return
  End If
  
  //Open the sound file in Windows
  Var tmp as New MemoryBlock(128)
  RetVal = mciSendString("open """ + TFShellPath.Value + """ type " + SoundType + " alias Sound_Device ", Tmp, 0, 0)
  If Retval <> 0 then
    MessageDialog.Show (ReturnErrorString(Retval))
    Return
  End If
End Sub

To get the song length in seconds, use this code:

Sub Action() Handles Action
  Var RetVal as Integer //Returned value or error
  Var tmp as New MemoryBlock(128)
  RetVal = mciSendString("status Sound_Device length", Tmp, tmp.Size, 0)
  
  Dim MyTime as UInt32
  Dim d as double = Val(tmp.WString(0))
  d = d/1000
  System.DebugLog(d.ToString + "seconds")  
End Sub

The mciSendString method was also changed to this:

Public Function mciSendString(lpszCommand as String, lpszReturnString as Ptr, cchReturn as UInt32, hWndCallback as Integer) As Integer
  #If TargetWindows
    Declare Function mciSendStringW lib "Winmm.dll" (lpszCommand as Wstring, _
    lpszReturnString as Ptr, cchReturn as UInt32, hWndCallback as Integer) as Integer
    Declare Function mciSendStringA lib "Winmm.dll" (lpszCommand as Cstring, _
    lpszReturnString as Ptr, cchReturn as UInt32, hWndCallback as Integer) as Integer
    If System.IsFunctionAvailable("mciSendStringW","Winmm.dll") Then
      Return mciSendStringW(lpszCommand, lpszReturnString, cchReturn, hWndCallback)
    Else
      Return mciSendStringA(lpszCommand, lpszReturnString, cchReturn, hWndCallback)
    End If
  #Else
    //System.DebugLog "This is not a Windows OS"
    Return 0
    
  #Endif
End Function

This works on 32-bit and 64-bit systems, tested on Windows 11, using Xojo 2023, r1

Edit: fix grammer

Hi Eugene & Julian,
thanks to your suggestions, now everything works. :partying_face:
If I want read data from a function I have to define the variable as Ptr and then associate it with a block of memory.