Imports System.Runtime.InteropServices
Namespace NCT.IaxClientWrapper.supported
Public Class NCT_IaxClientWrapper
Public Class NctIaxcEventArgsClass
Inherits System.EventArgs
Public eventType As NCT_IaxClientWrapper.EventTypes
Public iaxcEvent As Object
Public Sub New(ByVal e As Object, ByRef o As Object)
eventType = e
iaxcEvent = o
End Sub
End Class
Public Event IAXClientEvent(ByVal sender As Object, ByVal evt As NctIaxcEventArgsClass)
Public Function getCallInfo(ByVal callNo As Integer) As callInfo
If callNo <= UBound(calls) And callNo >= LBound(calls) Then
Return calls(callNo)
Else
Return (New callInfo)
End If
End Function
Public Function getCurrentInputLevel() As Single
Return CurrentInputLevel
End Function
Public Function getCurrentOutputLevel() As Single
Return CurrentOutputLevel
End Function
Public Class callInfo
Public numberptr As IntPtr = Marshal.AllocHGlobal(4)
Public number As String
Public callno As Integer
Public callstatus As CallStates
Public mediaformat As MediaFormats
Public remote As String
Public remoteName As String
Public local As String
Public localContext As String
Public videoFormat As Integer
Public videoWidth As Integer
Public videoHeight As Integer
Public videoUnsafeAddrPtr As Integer
Public netstat_rtt As Integer
Public LocalNetstats As iaxc_netstat
Public RemoteNetstats As iaxc_netstat
Public url As String
Public urlType As UrlReplyTypes
Public Sub setnumber(ByVal n As String)
number = n
numberptr = Marshal.StringToCoTaskMemAnsi(number)
End Sub
Protected Overrides Sub Finalize()
Try
Marshal.FreeHGlobal(numberptr)
Catch ex As Exception
End Try
MyBase.Finalize()
End Sub
End Class
Public Function getIaxcVersion() As String
Try
Dim strptr As IntPtr = Marshal.AllocHGlobal(256)
Dim version As String
iaxc_version(strptr.ToInt32)
version = Marshal.PtrToStringAnsi(strptr)
Marshal.FreeHGlobal(strptr)
Return version
Catch ex As Exception
Debug.WriteLine("Error trapped in iaxClientWrapper.version")
Debug.WriteLine(ex.StackTrace)
End Try
Return ""
End Function
Public Sub setCallerId(ByVal name As String, ByVal number As String)
Try
calleridname = Marshal.StringToCoTaskMemAnsi(name)
calleridnumber = Marshal.StringToCoTaskMemAnsi(number)
iaxc_set_callerid(calleridname.ToInt32, calleridnumber.ToInt32)
Catch ex As Exception
Debug.WriteLine("Error trapped in iaxClientWrapper.setcallerid")
Debug.WriteLine(ex.StackTrace)
End Try
End Sub
Public Sub sendDTMF(ByVal digit As Char)
Try
iaxc_send_dtmf(digit)
Catch ex As Exception
Debug.WriteLine("Error trapped in iaxClientWrapper.sendtext")
Debug.WriteLine(ex.StackTrace)
End Try
End Sub
Public Sub sendText(ByVal text As String)
Static textbin(50) As Object
Static textbinnext As Integer
Try
Dim ptrobj As New pointerholder(text)
textbin(textbinnext) = ptrobj
textbinnext = textbinnext + 1
If textbinnext > UBound(textbin) Then textbinnext = 0
textbin(textbinnext) = Nothing
iaxc_send_text(ptrobj.objectptr.ToInt32)
Catch ex As Exception
Debug.WriteLine("Error trapped in iaxClientWrapper.sendtext")
Debug.WriteLine(ex.StackTrace)
End Try
End Sub
Public Function stopSound(ByVal soundid As Integer) As Integer
Try
Dim n As Integer
If ptrlist.ContainsKey("soundid:" + soundid.ToString) Then
ptrlist.Remove("soundid:" + soundid.ToString)
End If
n = iaxc_stop_sound(soundid)
Return n
Catch ex As Exception
Debug.WriteLine("Error trapped in iaxClientWrapper.stopsound")
Debug.WriteLine(ex.StackTrace)
End Try
End Function
Public Function playSound(ByVal soundDef As iaxc_sound, Optional ByVal useRingOutputDevice As Boolean = False) As Integer
Try
Dim ptrobj As New pointerholder(soundDef)
Dim n As Integer
If useRingOutputDevice Then n = 1 Else n = 0
n = iaxc_play_sound(ptrobj.objectptr.ToInt32, n)
ptrlist.Add("soundid:" + n.ToString, ptrobj)
Return n
Catch ex As Exception
Debug.WriteLine("Error trapped in iaxClientWrapper.playsound")
Debug.WriteLine(ex.StackTrace)
End Try
End Function
Public Function selectCall(ByVal number As String) As Integer
If number <= UBound(calls) And number >= LBound(calls) Then
Try
System.Threading.Monitor.Enter(calls(number))
Dim n As Integer
n = iaxc_select_call(number)
System.Threading.Monitor.Exit(calls(number))
Return n
Catch ex As Exception
Debug.WriteLine("Error trapped in iaxClientWrapper.selectCall")
Debug.WriteLine(ex.StackTrace)
End Try
End If
End Function
Public Sub rejectCall(ByVal number As String)
If number <= UBound(calls) And number >= LBound(calls) Then
Try
Dim n As Integer
System.Threading.Monitor.Enter(calls(number))
n = calls(number).callstatus
If Not (n And CallStates.IAXC_CALL_STATE_RINGING) > 0 Then
Debug.WriteLine("That line isn't ringing")
Return
Else
iaxc_reject_call_number(number)
End If
System.Threading.Monitor.Exit(calls(number))
Catch ex As Exception
Debug.WriteLine("Error trapped in iaxClientWrapper.rejectCall")
Debug.WriteLine(ex.StackTrace)
End Try
End If
End Sub
Public Sub hangup(ByVal number As String)
dropCall(number)
End Sub
Public Sub dropCall(ByVal number As String)
If number <= UBound(calls) And number >= LBound(calls) Then
Try
Dim n As Integer
System.Threading.Monitor.Enter(calls(number))
n = calls(number).callstatus
If Not (n And CallStates.IAXC_CALL_STATE_ACTIVE) > 0 Then
Debug.WriteLine("That line isn't active")
Return
Else
n = iaxc_select_call(number)
If n >= 0 Then
iaxc_dump_call()
End If
End If
System.Threading.Monitor.Exit(calls(number))
Catch ex As Exception
Debug.WriteLine("Error trapped in iaxClientWrapper.DropCall")
Debug.WriteLine(ex.StackTrace)
End Try
End If
End Sub
Public Sub answerCall(ByVal number As String)
If number <= UBound(calls) And number >= LBound(calls) Then
Try
Dim n As Integer
System.Threading.Monitor.Enter(calls(number))
n = calls(number).callstatus
If Not (n And CallStates.IAXC_CALL_STATE_RINGING) > 0 Then
Debug.WriteLine("That line isn't ringing")
Return
Else
iaxc_answer_call(number)
End If
System.Threading.Monitor.Exit(calls(number))
Catch ex As Exception
Debug.WriteLine("Error trapped in iaxClientWrapper.AnswerCall")
Debug.WriteLine(ex.StackTrace)
End Try
End If
End Sub
Public Function placeCall(ByVal number As String) As Integer
System.Threading.Monitor.Enter(calls)
Dim callnumber As Integer
Dim n As Integer = 0
Try
callnumber = iaxc_first_free_call()
If callnumber < 0 Then
Debug.WriteLine("No available call lines.")
Return -1
End If
n = iaxc_select_call(callnumber)
If n < 0 Then
Debug.WriteLine("Unable to select free call")
Return -1
End If
calls(callnumber).setnumber(number)
iaxc_call(calls(callnumber).numberptr.ToInt32)
System.Threading.Monitor.Exit(calls)
Return callnumber
Catch ex As Exception
Debug.WriteLine("Error trapped in iaxClientWrapper.callout")
Debug.WriteLine(ex.StackTrace)
End Try
End Function
Public Function initialize(ByVal connectiontype As AudioTypes, ByVal MaxConcurrentCalls As Integer) As Boolean
Dim t As String = "This application was created using the NCT IaxClientWrapper library. " + _
"The library was" + Chr(13) + Chr(10) + "created by Andrew Pollack of Northern Collaborative Technologies " + _
"and may be used and" + Chr(13) + Chr(10) + "distributed subject to the following requirements: " + Chr(13) + Chr(10) _
+ Chr(13) + Chr(10) + _
"1. No money can be charged for any product of service which derives from this library. " _
+ Chr(13) + Chr(10) + Chr(13) + Chr(10) + _
"2. This message may not be removed, and must be displayed each time the library is used." _
+ Chr(13) + Chr(10) + Chr(13) + Chr(10) + _
"3. No attempt to reverse engineer or distribute any part of this library may be made." _
+ Chr(13) + Chr(10) + Chr(13) + Chr(10) + _
"4. The library is used at your own risk." _
+ Chr(13) + Chr(10) + Chr(13) + Chr(10) + Chr(13) + Chr(10) + _
"If you would like to use this library in any other way, contact andrewp@thenorth.com" _
+ Chr(13) + Chr(10) + Chr(13) + Chr(10) + Chr(13) + Chr(10) + _
"This library has been tested with build 566 of the IaxClientLibrary 'iaxclient.dll'. Visit " + Chr(13) + Chr(10) + _
"http://sourceforge.net/projects/iaxclient to find and build the latest version."
'MsgBox(t, MsgBoxStyle.SystemModal, "NCT IaxClientWrapper")
Dim n As Integer
Try
If Not clientInitialized Then
' initialize the call holders
Dim localcalls(MaxConcurrentCalls - 1) As callInfo
For n = 0 To UBound(localcalls)
localcalls(n) = New callInfo
Next
calls = localcalls
' make sure we have captured the handle first
If Me.captureEventHandle Then
' initialize with the given parameters
n = iaxc_initialize(connectiontype, MaxConcurrentCalls)
If Not n = 0 Then
Debug.WriteLine("Failed to intitialize IAX Client: " + n.ToString)
Return False
End If
' set up the event processing
n = iaxc_set_event_callpost(newprocptr, myeventid)
If Not n = 0 Then
Debug.WriteLine("Failed to setup event post routine: " + n.ToString)
Return False
End If
' start the processing thread
n = iaxc_start_processing_thread()
If Not n = 0 Then
Debug.WriteLine("Failed to start the processing thread: " + n.ToString)
Return False
End If
clientInitialized = True
Return True
Else
Debug.WriteLine("Failed to capture events. Exiting.")
Return False
End If
Else
Debug.WriteLine("Client is already initialized")
Return True
End If
Catch ex As Exception
Debug.WriteLine("Error trapped in iaxClientWrapper.initialize")
Debug.WriteLine(ex.StackTrace)
Return clientInitialized
End Try
End Function
Public Function unregister(ByVal regid As Integer) As Boolean
Dim n As Integer
Try
n = iaxc_unregister(regid)
If Not n > 0 Then
Debug.WriteLine("Failed to unregister id: " + regid.ToString + " [" + n.ToString + "]")
Return False
Else
Return True
End If
Catch ex As Exception
End Try
End Function
Public Function register(ByVal username As String, ByVal password As String, ByVal hostaddr As String) As Integer
Dim n As Integer
Dim regContainer As regUserInfo
Try
Dim regidkey As String = username + "::" + hostaddr
If reglist.ContainsKey(regidkey) Then
Debug.WriteLine("Removing existing registration first.")
regContainer = reglist.Item(regidkey)
unregister(regContainer.regid)
Else
regContainer = Nothing
End If
If regContainer Is Nothing Then
regContainer = New regUserInfo(username, password, hostaddr)
reglist.Add(regidkey, regContainer)
End If
n = iaxc_register(regContainer.usernameptr.ToInt32, regContainer.passwordptr.ToInt32, regContainer.serveraddrptr.ToInt32)
regContainer.regid = n
If reglist.ContainsKey(regContainer.regid.ToString) Then
reglist.Remove(regContainer.regid.ToString)
End If
reglist.Add(regContainer.regid.ToString, regContainer)
Return n
Catch ex As Exception
Debug.WriteLine("Error trapped in iaxClientWrapper.register")
Debug.WriteLine(ex.StackTrace)
Return clientInitialized
End Try
End Function
Private CurrentInputLevel As Single
Private CurrentOutputLevel As Single
Private Shared calleridname As IntPtr = Marshal.AllocHGlobal(4)
Private Shared calleridnumber As IntPtr = Marshal.AllocHGlobal(4)
Private Shared delegateHandle As GCHandle
Private Shared originalHandle As GCHandle
Private nwin As System.Windows.Forms.NativeWindow
Private Shared prevprocptr As Integer
Private Shared newprocptr As Integer
Private Shared myeventid As Integer
Private Shared thisdelegate As SubClassProcDelegate
Private Shared clientInitialized As Boolean = False
Private Shared eventHandleCaptured As Boolean = False
Private Shared reglist As Hashtable = New Hashtable
Private Shared ptrlist As Hashtable = New Hashtable
Private Shared calls() As callInfo
' The private classes for reguserinfo and pointerholder are used
' make sure that the required allocation of unmanaged memory is
' released any time of the object instances of them is destroyed
' by doing this in 'finalize()' we don't have to worry about it.
Public Class regUserInfo
Public usernameptr As IntPtr = Marshal.AllocHGlobal(4)
Public passwordptr As IntPtr = Marshal.AllocHGlobal(4)
Public serveraddrptr As IntPtr = Marshal.AllocHGlobal(4)
Public regid As Integer = 0
Public lastReply As Integer = 0
Public Sub New(ByVal username As String, ByVal password As String, ByVal serveraddr As String)
usernameptr = Marshal.StringToCoTaskMemAnsi(username)
passwordptr = Marshal.StringToCoTaskMemAnsi(password)
serveraddrptr = Marshal.StringToCoTaskMemAnsi(serveraddr)
End Sub
Protected Overrides Sub Finalize()
Try
Marshal.FreeHGlobal(usernameptr)
Marshal.FreeHGlobal(passwordptr)
Marshal.FreeHGlobal(serveraddrptr)
Catch ex As Exception
End Try
MyBase.Finalize()
End Sub
End Class
Private Class pointerholder
Public objectptr As IntPtr
Public obj As Object
Public Sub New(ByVal o As Object)
objectptr = Marshal.AllocHGlobal(Marshal.SizeOf(o))
obj = o
Marshal.StructureToPtr(o, objectptr, True)
End Sub
Protected Overrides Sub finalize()
Try
Marshal.FreeHGlobal(objectptr)
Catch ex As Exception
End Try
End Sub
End Class
#Region "IAXC Event Handlers - Internal to Class"
' CaptureEventHandle is called during initialize to make sure we get
' the event notifications from the dll
Private Function captureEventHandle() As Boolean
Try
If Not eventHandleCaptured Then
Dim cp As New System.Windows.Forms.CreateParams
cp.Caption = "NCT Internal Event Window"
cp.Style = cp.Style And (Not &H10000000)
nwin = New System.Windows.Forms.NativeWindow
nwin.CreateHandle(cp)
Randomize()
myeventid = Int(Rnd() * 10000) + 60000
thisdelegate = AddressOf Me.handler
' originalHandle = GCHandle.Alloc(Me.myinternalcontrol.Handle, GCHandleType.Pinned)
originalHandle = GCHandle.Alloc(Me.nwin.Handle, GCHandleType.Pinned)
' newprocptr = Me.myinternalcontrol.Handle.ToInt32
newprocptr = Me.nwin.Handle.ToInt32
delegateHandle = GCHandle.Alloc(thisdelegate)
prevprocptr = SetWindowLong(newprocptr, -4, thisdelegate)
eventHandleCaptured = True
Else
Debug.WriteLine("Event handle already captured")
End If
Catch ex As Exception
eventHandleCaptured = False
Debug.WriteLine("Error capturing event handle")
Debug.WriteLine(ex.StackTrace)
End Try
Return eventHandleCaptured
End Function
' handler() is method that actually receives the native window messages
' and dispatches the ones we want to deal with to processevent()
Private Function handler(ByVal hwnd As Integer, ByVal msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
If msg = myeventid Then
processEvent(lParam)
Call iaxc_free_event(lParam)
Return 1
Else
Return callwindowproc(prevprocptr, hwnd, msg, wParam, lParam)
End If
End Function
' processevent() recieves the event as an undefined object type and
' determines what kind of event it is. Once determined, the object is cast
' to the correct event type and read from unmanaged memory, then dispatched
' to one of the overloaded processevent() types below
Private Function processEvent(ByVal srcPtr As Integer) As Object
Dim ptr As IntPtr = New IntPtr(srcPtr)
' ** we don't have to worry about nextevt because we are
' using the post via OS method -- they all get to us in time
Dim nextevt As Integer = Marshal.ReadInt32(ptr, 0)
Dim type As Integer = Marshal.ReadInt32(ptr, 4)
Dim localeventcopy As NctIaxcEventArgsClass
Select Case type
Case 1 ' text
Dim o As iaxc_ev_text = _
(CType(Marshal.PtrToStructure _
(ptr, GetType(iaxc_ev_text)), iaxc_ev_text))
localeventcopy = New NctIaxcEventArgsClass(type, CType(o, Object))
processEvent(o)
RaiseEvent IAXClientEvent(Me, localeventcopy)
Case 2 ' Levels
Dim o As iaxc_ev_levels = _
(CType(Marshal.PtrToStructure( _
ptr, GetType(iaxc_ev_levels)), iaxc_ev_levels))
localeventcopy = New NctIaxcEventArgsClass(type, CType(o, Object))
processEvent(o)
RaiseEvent IAXClientEvent(Me, localeventcopy)
Case 3 ' State
Dim o As iaxc_ev_call_state = _
(CType(Marshal.PtrToStructure( _
ptr, GetType(iaxc_ev_call_state)), iaxc_ev_call_state))
localeventcopy = New NctIaxcEventArgsClass(type, CType(o, Object))
processEvent(o)
RaiseEvent IAXClientEvent(Me, localeventcopy)
Case 4 ' Netstat
Dim o As iaxc_ev_netstats = _
(CType(Marshal.PtrToStructure( _
ptr, GetType(iaxc_ev_netstats)), iaxc_ev_netstats))
localeventcopy = New NctIaxcEventArgsClass(type, CType(o, Object))
processEvent(o)
RaiseEvent IAXClientEvent(Me, localeventcopy)
Case 5 ' URL
Dim o As iaxc_ev_url = _
(CType(Marshal.PtrToStructure( _
ptr, GetType(iaxc_ev_url)), iaxc_ev_url))
localeventcopy = New NctIaxcEventArgsClass(type, CType(o, Object))
processEvent(o)
RaiseEvent IAXClientEvent(Me, localeventcopy)
Case 6 ' Video
Dim o As iaxc_ev_video = _
(CType(Marshal.PtrToStructure( _
ptr, GetType(iaxc_ev_video)), iaxc_ev_video))
localeventcopy = New NctIaxcEventArgsClass(type, CType(o, Object))
processEvent(o)
RaiseEvent IAXClientEvent(Me, localeventcopy)
Case 7 ' Registration
Dim o As iaxc_ev_registration = _
(CType(Marshal.PtrToStructure( _
ptr, GetType(iaxc_ev_registration)), iaxc_ev_registration))
localeventcopy = New NctIaxcEventArgsClass(type, CType(o, Object))
processEvent(o)
RaiseEvent IAXClientEvent(Me, localeventcopy)
End Select
Return 0
End Function
' each of the processevent() overloads below handles a specific kind of
' event, updating things in this class as needed.
Private Sub processevent(ByVal evt As iaxc_ev_text)
'nothing is required
End Sub
Private Sub processevent(ByVal evt As iaxc_ev_levels)
If Not ((CurrentInputLevel = evt.input) And (CurrentOutputLevel = evt.output)) Then
CurrentInputLevel = evt.input
CurrentOutputLevel = evt.output
End If
End Sub
Private Sub processevent(ByVal evt As iaxc_ev_registration)
If reglist.ContainsKey(evt.id.ToString) Then
Dim userreg As regUserInfo = reglist.Item(evt.id.ToString)
If Not userreg Is Nothing Then userreg.lastReply = evt.reply
End If
End Sub
Private Sub processevent(ByVal evt As iaxc_ev_call_state)
System.Threading.Monitor.Enter(calls)
calls(evt.callno).callstatus = evt.state
calls(evt.callno).mediaformat = evt.format
calls(evt.callno).remote = evt.remote
calls(evt.callno).remoteName = evt.remote_name
calls(evt.callno).local = evt.local
calls(evt.callno).localContext = evt.local_context
If evt.state And CallStates.IAXC_CALL_STATE_FREE Then
calls(evt.callno).videoFormat = 0
calls(evt.callno).videoHeight = 0
calls(evt.callno).videoWidth = 0
calls(evt.callno).videoUnsafeAddrPtr = 0
calls(evt.callno).url = ""
calls(evt.callno).urlType = 0
Dim ns As iaxc_netstat
calls(evt.callno).RemoteNetstats = ns
calls(evt.callno).LocalNetstats = ns
calls(evt.callno).netstat_rtt = 0
End If
System.Threading.Monitor.Exit(calls)
End Sub
Private Sub processevent(ByVal evt As iaxc_ev_video)
System.Threading.Monitor.Enter(calls)
calls(evt.callno).videoFormat = evt.format
calls(evt.callno).videoHeight = evt.height
calls(evt.callno).videoWidth = evt.width
calls(evt.callno).videoUnsafeAddrPtr = evt.datapointer
System.Threading.Monitor.Exit(calls)
End Sub
Private Sub processevent(ByVal evt As iaxc_ev_netstats)
System.Threading.Monitor.Enter(calls)
calls(evt.callno).netstat_rtt = evt.rtt
calls(evt.callno).LocalNetstats = evt.local
calls(evt.callno).RemoteNetstats = evt.remote
System.Threading.Monitor.Exit(calls)
End Sub
Private Sub processevent(ByVal evt As iaxc_ev_url)
System.Threading.Monitor.Enter(calls)
calls(evt.callno).url = evt.url
calls(evt.callno).urlType = evt.urltype
System.Threading.Monitor.Exit(calls)
End Sub
#End Region
#Region "IAXC Enumerations"
Enum MediaFormats As Integer
IAXC_FORMAT_g723_1 = (1 << 0)
IAXC_FORMAT_GSM = (1 << 1)
IAXC_FORMAT_ULAW = (1 << 2)
IAXC_FORMAT_ALAW = (1 << 3)
IAXC_FORMAT_G726 = (1 << 4)
IAXC_FORMAT_ADPCM = (1 << 5)
IAXC_FORMAT_SLINEAR = (1 << 6)
IAXC_FORMAT_LPC10 = (1 << 7)
IAXC_FORMAT_G729A = (1 << 8)
IAXC_FORMAT_SPEEX = (1 << 9)
IAXC_FORMAT_ILBC = (1 << 10)
IAXC_FORMAT_MAX_AUDIO = (1 << 15)
IAXC_FORMAT_JPEG = (1 << 16)
IAXC_FORMAT_PNG = (1 << 17)
IAXC_FORMAT_H261 = (1 << 18)
IAXC_FORMAT_H263 = (1 << 19)
IAXC_FORMAT_H263_PLUS = (1 << 20)
IAXC_FORMAT_MPEG4 = (1 << 21)
IAXC_FORMAT_H264 = (1 << 23)
IAXC_FORMAT_THEORA = (1 << 24)
End Enum
Enum AudioTypes As Integer
AUDIO_INTERNAL_PA = 1
AUDIO_INTERNAL_FILE_UNSUPPORTED = 2
AUDIO_INTERNAL_ALSA_UNSUPPORTED = 3
AUDIO_INTERNAL_PA_PRESETMIXER = 4
AUDIO_EXTERNAL_UNSUPPORTED = 99
End Enum
Public Enum EventTypes
IAXC_EVENT_TEXT = 1
IAXC_EVENT_LEVELS = 2
IAXC_EVENT_STATE = 3
IAXC_EVENT_NETSTAT = 4
IAXC_EVENT_URL = 5 ' URL push via IAX(2)
IAXC_EVENT_VIDEO = 6 ' video data (pointer)
IAXC_EVENT_REGISTRATION = 7
End Enum
Public Enum CallStates
IAXC_CALL_STATE_FREE = 0
IAXC_CALL_STATE_ACTIVE = (1 << 1)
IAXC_CALL_STATE_OUTGOING = (1 << 2)
IAXC_CALL_STATE_RINGING = (1 << 3)
IAXC_CALL_STATE_COMPLETE = (1 << 4)
IAXC_CALL_STATE_SELECTED = (1 << 5)
IAXC_CALL_STATE_BUSY = (1 << 6)
IAXC_CALL_STATE_TRANSFER = (1 << 7)
End Enum
Public Enum TextEventTypes
IAXC_TEXT_TYPE_STATUS = 1
IAXC_TEXT_TYPE_NOTICE = 2
IAXC_TEXT_TYPE_ERROR = 3
' FATAL ERROR: User Agent should probably display error, then die.
IAXC_TEXT_TYPE_FATALERROR = 4
IAXC_TEXT_TYPE_IAX = 5
End Enum
Public Enum RegistrationReplyTypes
IAXC_REGISTRATION_REPLY_ACK = 18 ' IAX_EVENT_REGACC
IAXC_REGISTRATION_REPLY_REJ = 30 ' IAX_EVENT_REGREJ
IAXC_REGISTRATION_REPLY_TIMEOUT = 6 ' IAX_EVENT_TIMEOUT
End Enum
Public Enum UrlReplyTypes
IAXC_URL_URL = 1 ' URL received
IAXC_URL_LDCOMPLETE = 2 ' URL loading complete
IAXC_URL_LINKURL = 3 ' URL link request
IAXC_URL_LINKREJECT = 4 ' URL link reject
IAXC_URL_UNLINK = 5 ' URL unlink
End Enum
'Friend Const IAXC_EVENT_BUFSIZ = 256
Public Enum AudioDeviceTypes
IAXC_AD_INPUT = (1 << 0)
IAXC_AD_OUTPUT = (1 << 1)
IAXC_AD_RING = (1 << 2)
IAXC_AD_INPUT_DEFAULT = (1 << 3)
IAXC_AD_OUTPUT_DEFAULT = (1 << 4)
IAXC_AD_RING_DEFAULT = (1 << 5)
End Enum
Public Enum FilterTypes
IAXC_FILTER_DENOISE = (1 << 0)
IAXC_FILTER_AGC = (1 << 1)
IAXC_FILTER_ECHO = (1 << 2)
IAXC_FILTER_AAGC = (1 << 3) ' Analog (mixer-based) AGC
IAXC_FILTER_CN = (1 << 4) ' Send CN frames when silence detected
End Enum
#End Region
#Region "IAXC INTERNAL STRUCTURES"
Public Structure iaxc_ev_levels
Friend nextEvent As Integer
Friend eventtype As Integer
Public input As Single
Public output As Single
End Structure
Public Structure iaxc_ev_text
Friend nextEvent As Integer
Friend eventtype As Integer
Public type As Int32
Public callno As Int32
<MarshalAsAttribute(UnmanagedType.ByValTStr, sizeconst:=256)> Public text As String
End Structure
Public Structure iaxc_ev_call_state
Friend nextEvent As Integer
Friend eventtype As Integer
Public callno As Int32
Public state As Int32
Public format As Int32
<MarshalAsAttribute(UnmanagedType.ByValTStr, sizeconst:=256)> Public remote As String
<MarshalAsAttribute(UnmanagedType.ByValTStr, sizeconst:=256)> Public remote_name As String
<MarshalAsAttribute(UnmanagedType.ByValTStr, sizeconst:=256)> Public local As String
<MarshalAsAttribute(UnmanagedType.ByValTStr, sizeconst:=256)> Public local_context As String
End Structure
Public Structure iaxc_netstat
Public jitter As Int32
Public losspct As Int32
Public losscnt As Int32
Public packets As Int32
Public delay As Int32
Public dropped As Int32
Public ooo As Int32
End Structure
Public Structure iaxc_ev_netstats
Friend nextEvent As Integer
Friend eventtype As Integer
Public callno As Int32
Public rtt As Int32
Public local As iaxc_netstat
Public remote As iaxc_netstat
End Structure
Public Structure iaxc_ev_url
Friend nextEvent As Integer
Friend eventtype As Integer
Public callno As Int32
Public urltype As Int32
<MarshalAsAttribute(UnmanagedType.ByValTStr, sizeconst:=256)> Public url As String
End Structure
Public Structure iaxc_ev_video
Friend nextEvent As Integer
Friend eventtype As Integer
Public callno As Int32
Public format As Int32
Public width As Int32
Public height As Int32
Public datapointer As Long
End Structure
Public Structure iaxc_ev_registration
Friend nextEvent As Integer
Friend eventtype As Integer
Public id As Int32
Public reply As Int32
Public msgcount As Int32
End Structure
Public Structure iaxc_audio_device
Public devnameptrint As Integer
Public caps As Int32
Public devid As Integer
Public name As String
End Structure
Public Structure iaxc_sound
Public dataAddr As Int16
Public length As Long
Public malloced As Integer '/* should the library free() the data after being played? */
Public channel As Integer '/* 0 for outpub selected, 1 for ringselected */
Public repeat As Integer '/* -1 for inifinite */
Public position As Long '/* internal */
Public id As Integer '/* internal */
Public addrOfNextSound As Integer
End Structure
#End Region
' The finalize event makes sure we de-allocate memory in a few places we
' have allocated it in unmanaged resources
Protected Overrides Sub finalize()
Try
If clientInitialized Then iaxc_shutdown()
Catch ex As Exception
Debug.WriteLine(ex.StackTrace)
End Try
Try
delegateHandle.Free()
originalHandle.Free()
Marshal.FreeHGlobal(calleridname)
Marshal.FreeHGlobal(calleridnumber)
Catch ex As Exception
End Try
MyBase.Finalize()
End Sub
Private Sub NCT_IaxClientWrapper_IAXClientEvent(ByVal sender As Object, ByVal evt As NctIaxcEventArgsClass) Handles Me.IAXClientEvent
End Sub
End Class
Module WinAPIcalls
' Resets the window handle used by the OS to pass event messages to our own handler
Declare Function SetWindowLong Lib "USER32.DLL" Alias "SetWindowLongA" ( _
ByVal hwnd As Integer, ByVal attr As Integer, _
ByVal lVal As SubClassProcDelegate) As Integer
' Used to pass a message to another handler - we use this to call the native window
' handler for any events we get that we're not dealing with ourselves, since we have
' intercepted all the events and if we don't do this, they won't get handled.
Declare Function callwindowproc Lib "user32.dll" Alias "CallWindowProcA" ( _
ByVal prevprocptr As Integer, ByVal hwnd As Integer, _
ByVal msg As Integer, ByVal wparam As Integer, ByVal lparam As Integer) As Integer
' Creates a delegate object to assign the address of a method with a match signature
Delegate Function SubClassProcDelegate( _
ByVal hwnd As Integer, ByVal msg As Integer, _
ByVal wParam As Integer, ByVal lParam As Integer) As Integer
End Module
Module iaxc_function_calls
Friend Declare Sub iaxc_answer_call Lib "iaxclient.dll" Alias "iaxc_answer_call" (ByVal callno As Integer)
Friend Declare Function iaxc_audio_devices_get Lib "iaxclient.dll" Alias "iaxc_audio_devices_get" (ByVal devlistptrInt As Integer, ByVal ndevsptrInt As Integer, ByVal InputptrInt As Integer, ByVal OutputptrInt As Integer, ByVal ringptrInt As Integer) As Integer
Friend Declare Sub iaxc_audio_devices_set Lib "iaxclient.dll" Alias "iaxc_audio_devices_set" (ByVal input As Integer, ByVal output As Integer, ByVal ring As Integer)
Friend Declare Sub iaxc_blind_transfer_call Lib "iaxclient.dll" Alias "iaxc_blind_transfer_call" (ByVal callNo As Integer, ByVal number As Integer)
Friend Declare Sub iaxc_call Lib "iaxclient.dll" Alias "iaxc_call" (ByVal callto As Integer)
Friend Declare Sub iaxc_dump_all_calls Lib "iaxclient.dll" Alias "iaxc_dump_all_calls" ()
Friend Declare Sub iaxc_dump_call Lib "iaxclient.dll" Alias "iaxc_dump_call" ()
Friend Declare Function iaxc_first_free_call Lib "iaxclient.dll" Alias "iaxc_first_free_call" () As Integer
Friend Declare Sub iaxc_free_event Lib "iaxclient.dll" Alias "iaxc_free_event" (ByVal eventHandle As Integer)
Friend Declare Function iaxc_get_event_levels Lib "iaxclient.dll" Alias "iaxc_get_event_levels" (ByVal evtAddr As Integer) As Integer
Friend Declare Function iaxc_get_event_state Lib "iaxclient.dll" Alias "iaxc_get_event_state" (ByVal evtAddr As Integer) As Integer
Friend Declare Function iaxc_get_event_text Lib "iaxclient.dll" Alias "iaxc_get_event_text" (ByVal evtAddr As Integer) As Integer
Friend Declare Function iaxc_get_filters Lib "iaxclient.dll" Alias "iaxc_get_filters" () As Integer
Friend Declare Function iaxc_get_netstats Lib "iaxclient.dll" Alias "iaxc_get_netstats" (ByVal callno As Integer, ByVal addrOfRTT As Integer, ByVal netStatAddrLocal As Integer, ByVal netStatAddrRemote As Integer) As Integer
Friend Declare Function iaxc_initialize Lib "iaxclient.dll" Alias "iaxc_initialize" (ByVal audtype As Int32, ByVal ncalls As Int32) As Int32
Friend Declare Function iaxc_input_level_get Lib "iaxclient.dll" Alias "iaxc_input_level_get" () As Double
Friend Declare Function iaxc_input_level_set Lib "iaxclient.dll" Alias "iaxc_input_level_set" (ByVal level As Double) As Integer
Friend Declare Sub iaxc_keep_default_input_line Lib "iaxclient.dll" Alias "iaxc_keep_default_input_line" (ByVal OneEqualsTrue As Integer)
Friend Declare Function iaxc_mic_boost_get Lib "iaxclient.dll" Alias "iaxc_mic_boost_get" () As Integer
Friend Declare Function iaxc_mic_boost_set Lib "iaxclient.dll" Alias "iaxc_mic_boost_set" (ByVal level As Integer) As Integer
Friend Declare Sub iaxc_millisleep Lib "iaxclient.dll" Alias "iaxc_millisleep" (ByVal milliseconds As Long)
Friend Declare Function iaxc_output_level_get Lib "iaxclient.dll" Alias "iaxc_output_level_get" () As Double
Friend Declare Function iaxc_output_level_set Lib "iaxclient.dll" Alias "iaxc_output_level_set" (ByVal level As Double) As Integer
Friend Declare Function iaxc_play_sound Lib "iaxclient.dll" Alias "iaxc_play_sound" (ByVal soundStructAddr As Integer, ByVal outdevice As Integer) As Integer
Friend Declare Sub iaxc_process_calls Lib "iaxclient.dll" Alias "iaxc_process_calls" ()
Friend Declare Function iaxc_quelch Lib "iaxclient.dll" Alias "iaxc_quelch" (ByVal callno As Integer) As Integer
Friend Declare Function iaxc_register Lib "iaxclient.dll" Alias "iaxc_register" (ByVal user As Integer, ByVal pass As Integer, ByVal host As Integer) As Int32
Friend Declare Sub iaxc_reject_call Lib "iaxclient.dll" Alias "iaxc_reject_call" ()
Friend Declare Sub iaxc_reject_call_number Lib "iaxclient.dll" Alias "iaxc_reject_call_number" (ByVal callno As Integer)
Friend Declare Function iaxc_select_call Lib "iaxclient.dll" Alias "iaxc_select_call" (ByVal callno As Integer) As Integer
Friend Declare Function iaxc_selected_call Lib "iaxclient.dll" Alias "iaxc_selected_call" () As Integer
Friend Declare Sub iaxc_send_dtmf Lib "iaxclient.dll" Alias "iaxc_send_dtmf" (ByVal digit As Char)
Friend Declare Sub iaxc_send_text Lib "iaxclient.dll" Alias "iaxc_send_text" (ByVal textAddr As Integer)
Friend Declare Sub iaxc_send_url Lib "iaxclient.dll" Alias "iaxc_send_url" (ByVal urlAddr As Integer, ByVal link As Integer)
Friend Declare Sub iaxc_set_audio_output Lib "iaxclient.dll" Alias "iaxc_set_audio_output" (ByVal output As Int32)
Friend Declare Sub iaxc_set_callerid Lib "iaxclient.dll" Alias "iaxc_set_callerid" (ByVal nameAddr As Integer, ByVal numberAddr As Integer)
Friend Declare Sub iaxc_set_event_callback Lib "iaxclient.dll" Alias "iaxc_set_event_callback" (ByVal callBackDelegateAddr As Int32)
Friend Declare Function iaxc_set_event_callpost Lib "iaxclient.dll" Alias "iaxc_set_event_callpost" (ByVal hwnd As Integer, ByVal id As Integer) As Integer
Friend Declare Function iaxc_set_files Lib "iaxclient.dll" Alias "iaxc_set_files" (ByVal inputFileAddr As Integer, ByVal outputFileAddr As Integer) As Integer
Friend Declare Sub iaxc_set_filters Lib "iaxclient.dll" Alias "iaxc_set_filters" (ByVal filters As Integer)
Friend Declare Sub iaxc_set_formats Lib "iaxclient.dll" Alias "iaxc_set_formats" (ByVal preferred As Int32, ByVal allows As Int32)
Friend Declare Sub iaxc_set_min_outgoing_framesize Lib "iaxclient.dll" Alias "iaxc_set_min_outgoing_framesize" (ByVal samples As Integer)
Friend Declare Sub iaxc_set_networking Lib "iaxclient.dll" Alias "iaxc_set_networking" (ByVal sendToFunctionDelegateAddr As Integer, ByVal recvFromFunctionDelegateAddr As Integer)
Friend Declare Sub iaxc_set_preferred_source_udp_port Lib "iaxclient.dll" Alias "iaxc_set_preferred_source_udp_port" (ByVal udpPort As Integer)
Friend Declare Sub iaxc_set_silence_threshold Lib "iaxclient.dll" Alias "iaxc_set_silence_threshold" (ByVal val As Double)
Friend Declare Sub iaxc_set_speex_settings Lib "iaxclient.dll" Alias "iaxc_set_speex_settings" (ByVal decodeEnhance As Integer, ByVal quality As Single, ByVal bitrate As Integer, ByVal vbr As Integer, ByVal abr As Integer, ByVal complexity As Integer)
Friend Declare Sub iaxc_shutdown Lib "iaxclient.dll" Alias "iaxc_shutdown" ()
Friend Declare Function iaxc_start_processing_thread Lib "iaxclient.dll" Alias "iaxc_start_processing_thread" () As Int32
Friend Declare Function iaxc_stop_processing_thread Lib "iaxclient.dll" Alias "iaxc_stop_processing_thread" () As Integer
Friend Declare Function iaxc_stop_sound Lib "iaxclient.dll" Alias "iaxc_stop_sound" (ByVal id As Integer) As Integer
Friend Declare Function iaxc_unquelch Lib "iaxclient.dll" Alias "iaxc_unquelch" (ByVal callno As Integer) As Integer
Friend Declare Function iaxc_unregister Lib "iaxclient.dll" Alias "iaxc_unregister" (ByVal id As Integer) As Integer
Friend Declare Function iaxc_version Lib "iaxclient.dll" Alias "iaxc_version" (ByVal versionStringAddr As Integer) As Integer
End Module
End Namespace
Namespace NCT.IaxClientWrapper.Unsupported
Public Module iaxc_function_calls
Public Declare Sub iaxc_answer_call Lib "iaxclient.dll" Alias "iaxc_answer_call" (ByVal callno As Integer)
'Public Declare Function iaxc_audio_devices_get Lib "iaxclient.dll" Alias "iaxc_audio_devices_get" (ByVal devlistptrInt As Integer, ByVal ndevsptrInt As Integer, ByVal InputptrInt As Integer, ByVal OutputptrInt As Integer, ByVal ringptrInt As Integer) As Integer
Public Declare Function iaxc_audio_devices_get Lib "iaxclient.dll" Alias "iaxc_audio_devices_get" (ByRef devlistptrInt As IntPtr, ByRef ndevsptrInt As Integer, ByRef InputptrInt As Integer, ByRef OutputptrInt As Integer, ByRef ringptrInt As Integer) As Integer
Public Declare Sub iaxc_audio_devices_set Lib "iaxclient.dll" Alias "iaxc_audio_devices_set" (ByVal input As Integer, ByVal output As Integer, ByVal ring As Integer)
Public Declare Sub iaxc_blind_transfer_call Lib "iaxclient.dll" Alias "iaxc_blind_transfer_call" (ByVal callNo As Integer, ByVal number As Integer)
Public Declare Sub iaxc_call Lib "iaxclient.dll" Alias "iaxc_call" (ByVal callto As Integer)
Public Declare Sub iaxc_dump_all_calls Lib "iaxclient.dll" Alias "iaxc_dump_all_calls" ()
Public Declare Sub iaxc_dump_call Lib "iaxclient.dll" Alias "iaxc_dump_call" ()
Public Declare Sub iaxc_first_free_call Lib "iaxclient.dll" Alias "iaxc_first_free_call" ()
Public Declare Sub iaxc_free_event Lib "iaxclient.dll" Alias "iaxc_free_event" (ByVal eventHandle As Integer)
Public Declare Function iaxc_get_event_levels Lib "iaxclient.dll" Alias "iaxc_get_event_levels" (ByVal evtAddr As Integer) As Integer
Public Declare Function iaxc_get_event_state Lib "iaxclient.dll" Alias "iaxc_get_event_state" (ByVal evtAddr As Integer) As Integer
Public Declare Function iaxc_get_event_text Lib "iaxclient.dll" Alias "iaxc_get_event_text" (ByVal evtAddr As Integer) As Integer
Public Declare Function iaxc_get_filters Lib "iaxclient.dll" Alias "iaxc_get_filters" () As Integer
Public Declare Function iaxc_get_netstats Lib "iaxclient.dll" Alias "iaxc_get_netstats" (ByVal callno As Integer, ByVal addrOfRTT As Integer, ByVal netStatAddrLocal As Integer, ByVal netStatAddrRemote As Integer) As Integer
Public Declare Function iaxc_initialize Lib "iaxclient.dll" Alias "iaxc_initialize" (ByVal audtype As Int32, ByVal ncalls As Int32) As Int32
Public Declare Function iaxc_input_level_get Lib "iaxclient.dll" Alias "iaxc_input_level_get" () As Double
Public Declare Function iaxc_input_level_set Lib "iaxclient.dll" Alias "iaxc_input_level_set" (ByVal level As Double) As Integer
Public Declare Sub iaxc_keep_default_input_line Lib "iaxclient.dll" Alias "iaxc_keep_default_input_line" (ByVal OneEqualsTrue As Integer)
Public Declare Function iaxc_mic_boost_get Lib "iaxclient.dll" Alias "iaxc_mic_boost_get" () As Integer
Public Declare Function iaxc_mic_boost_set Lib "iaxclient.dll" Alias "iaxc_mic_boost_set" (ByVal level As Integer) As Integer
Public Declare Sub iaxc_millisleep Lib "iaxclient.dll" Alias "iaxc_millisleep" (ByVal milliseconds As Long)
Public Declare Function iaxc_output_level_get Lib "iaxclient.dll" Alias "iaxc_output_level_get" () As Double
Public Declare Function iaxc_output_level_set Lib "iaxclient.dll" Alias "iaxc_output_level_set" (ByVal level As Double) As Integer
Public Declare Function iaxc_play_sound Lib "iaxclient.dll" Alias "iaxc_play_sound" (ByVal soundStructAddr As Integer, ByVal outdevice As Integer) As Integer
Public Declare Sub iaxc_process_calls Lib "iaxclient.dll" Alias "iaxc_process_calls" ()
Public Declare Function iaxc_quelch Lib "iaxclient.dll" Alias "iaxc_quelch" (ByVal callno As Integer) As Integer
Public Declare Function iaxc_register Lib "iaxclient.dll" Alias "iaxc_register" (ByVal user As Integer, ByVal pass As Integer, ByVal host As Integer) As Int32
Public Declare Sub iaxc_reject_call Lib "iaxclient.dll" Alias "iaxc_reject_call" ()
Public Declare Sub iaxc_reject_call_number Lib "iaxclient.dll" Alias "iaxc_reject_call_number" (ByVal callno As Integer)
Public Declare Function iaxc_select_call Lib "iaxclient.dll" Alias "iaxc_select_call" (ByVal callno As Integer) As Integer
Public Declare Function iaxc_selected_call Lib "iaxclient.dll" Alias "iaxc_selected_call" () As Integer
Public Declare Sub iaxc_send_dtmf Lib "iaxclient.dll" Alias "iaxc_send_dtmf" (ByVal digit As Char)
Public Declare Sub iaxc_send_text Lib "iaxclient.dll" Alias "iaxc_send_text" (ByVal textAddr As Integer)
Public Declare Sub iaxc_send_url Lib "iaxclient.dll" Alias "iaxc_send_url" (ByVal urlAddr As Integer, ByVal link As Integer)
Public Declare Sub iaxc_set_audio_output Lib "iaxclient.dll" Alias "iaxc_set_audio_output" (ByVal output As Int32)
Public Declare Sub iaxc_set_callerid Lib "iaxclient.dll" Alias "iaxc_set_callerid" (ByVal nameAddr As Integer, ByVal numberAddr As Integer)
Public Declare Sub iaxc_set_event_callback Lib "iaxclient.dll" Alias "iaxc_set_event_callback" (ByVal callBackDelegateAddr As Int32)
Public Declare Function iaxc_set_event_callpost Lib "iaxclient.dll" Alias "iaxc_set_event_callpost" (ByVal hwnd As Integer, ByVal id As Integer) As Integer
Public Declare Function iaxc_set_files Lib "iaxclient.dll" Alias "iaxc_set_files" (ByVal inputFileAddr As Integer, ByVal outputFileAddr As Integer) As Integer
Public Declare Sub iaxc_set_filters Lib "iaxclient.dll" Alias "iaxc_set_filters" (ByVal filters As Integer)
Public Declare Sub iaxc_set_formats Lib "iaxclient.dll" Alias "iaxc_set_formats" (ByVal preferred As Int32, ByVal allows As Int32)
Public Declare Sub iaxc_set_min_outgoing_framesize Lib "iaxclient.dll" Alias "iaxc_set_min_outgoing_framesize" (ByVal samples As Integer)
Public Declare Sub iaxc_set_networking Lib "iaxclient.dll" Alias "iaxc_set_networking" (ByVal sendToFunctionDelegateAddr As Integer, ByVal recvFromFunctionDelegateAddr As Integer)
Public Declare Sub iaxc_set_preferred_source_udp_port Lib "iaxclient.dll" Alias "iaxc_set_preferred_source_udp_port" (ByVal udpPort As Integer)
Public Declare Sub iaxc_set_silence_threshold Lib "iaxclient.dll" Alias "iaxc_set_silence_threshold" (ByVal val As Double)
Public Declare Sub iaxc_set_speex_settings Lib "iaxclient.dll" Alias "iaxc_set_speex_settings" (ByVal decodeEnhance As Integer, ByVal quality As Single, ByVal bitrate As Integer, ByVal vbr As Integer, ByVal abr As Integer, ByVal complexity As Integer)
Public Declare Sub iaxc_shutdown Lib "iaxclient.dll" Alias "iaxc_shutdown" ()
Public Declare Function iaxc_start_processing_thread Lib "iaxclient.dll" Alias "iaxc_start_processing_thread" () As Int32
Public Declare Function iaxc_stop_processing_thread Lib "iaxclient.dll" Alias "iaxc_stop_processing_thread" () As Integer
Public Declare Function iaxc_stop_sound Lib "iaxclient.dll" Alias "iaxc_stop_sound" (ByVal id As Integer) As Integer
Public Declare Function iaxc_unquelch Lib "iaxclient.dll" Alias "iaxc_unquelch" (ByVal callno As Integer) As Integer
Public Declare Function iaxc_unregister Lib "iaxclient.dll" Alias "iaxc_unregister" (ByVal id As Integer) As Integer
Public Declare Function iaxc_version Lib "iaxclient.dll" Alias "iaxc_version" (ByVal versionStringAddr As Integer) As Integer
Function GetAudio() As Collection
Dim retDevices As New Collection
Dim ptrDevices As IntPtr = IntPtr.Zero
Dim nDevs As Integer = 0
Dim input As Integer = 0
Dim output As Integer = 0
Dim ring As Integer = 0
iaxc_audio_devices_get(ptrDevices, nDevs, input, output, ring)
If nDevs > 0 Then
Dim current As IntPtr = ptrDevices
Dim device As supported.NCT_IaxClientWrapper.iaxc_audio_device
Dim i As Integer = 0
For i = 0 To nDevs - 2
device = CType(Marshal.PtrToStructure(current, GetType(supported.NCT_IaxClientWrapper.iaxc_audio_device)), supported.NCT_IaxClientWrapper.iaxc_audio_device)
retDevices.Add(device)
Marshal.DestroyStructure(current, GetType(supported.NCT_IaxClientWrapper.iaxc_audio_device))
'current = CType((CType(current, Integer) + Marshal.SizeOf(device)), IntPtr)
current = CType((CType(current, Integer) + 12), IntPtr)
'System.Math.Min(System.Threading.Interlocked.Increment(i), i - 1)
Console.Write(device.name & vbCrLf)
device = Nothing
Next
Marshal.FreeCoTaskMem(ptrDevices)
End If
Return retDevices
End Function
End Module
End Namespace