I apolgize for the length. My program is an intermediary program. It sits between a winlirc server. Winlirc is a program at interprets the signals from an infrared remote control and then sends its interpretation to all clients connected to the server. My program connects to the winlirc server, waits for something to be sent to it from the winlirc server, processes the input, and then uses the processed input to send a command, using some pieces of the winamp api, to foobar2000.

This program has been a lot of learning for me and much of it I still don't fully understand. Sockets being the least understood of the whole program. I have a few bugs left to work out. One of which happens to be in the timers. Any time a timer is run it starts sucking up 100% of my cpu. I need some way for a delay between processing input from the winlirc server that doesn't eat cpu time like mad. Another bug which I think stems somewhat from the way sockets are handled seems to process two seperate inputs and runs them both at the same time, which shouldn't be possible. And yes much of this is hard coded. I have no intention to put the work into this program to make it capable of being configured without having the source code and visual studio.

I'd appreciate any comments you may have on this code or any ways to make it better. It's hard to learn how to do things the right way without some guidance.

Also my comments suck.. or they are sucky attempts at humor, just ignore em. :P

VB Code:
  1. Option Strict On
  2.  
  3. Module Module1
  4.     'Global variable describing if the program is active or not.
  5.     'will be set by the system tray icon.
  6.     Dim gIsActive As Boolean = True
  7.     Dim mBytes(1024) As Byte
  8.  
  9.     'Dim mTrayIconCreated As Boolean = False
  10.  
  11.     'Supar sekret MAGICAL MSDN code...
  12.     'creates a new socket
  13.     Dim LIRCSocket As New System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp)
  14.     'Resolves a hostname
  15.     Dim ipHostInfo As System.Net.IPHostEntry = System.Net.Dns.Resolve("172.16.1.69")
  16.     'Does something
  17.     Dim ipas As System.Net.IPAddress = ipHostInfo.AddressList(0)
  18.  
  19.     'ipas is the ipaddress of the target machine, 8765 is the socket we want to connect to on the target machine
  20.     Dim RemoteIP As New System.Net.IPEndPoint(ipas, 8765)
  21.  
  22.     Dim Start, Finish As Double
  23.  
  24.     'if this is true then we are connected to the lirc server
  25.     Public mIsConnected As Boolean
  26.  
  27.     'Holds the last key that was pressed
  28.     'Dim mLastKeyPressed As String = ""
  29.  
  30.     'holes the number of times the last key was pressed
  31.     'Dim mLastKeyPressedTimes As Integer
  32.  
  33.     'Sets whether or not the program is finished.
  34.     Public mIsFinished As Boolean = False
  35.  
  36.     'Volume of Foobar
  37.     'Public mVolume As Integer
  38.  
  39.     'Is foobar paused or not?  This variable has the answer!
  40.     Dim mFoobarPaused As Boolean
  41.  
  42. #Region "WINAMP API"
  43.     ' Window Messages to use with SendMessageByString and SendMessageLong.
  44.     Public Const WM_COMMAND As Integer = &H111
  45.     Public Const WM_USER As Integer = &H400
  46.  
  47.     '' WM_COMMAND Winamp API IDs.
  48.     Public Const WA_NEXT As Integer = 40048
  49.     Public Const WA_PAUSE As Integer = 40046
  50.     Public Const WA_PLAY As Integer = 40045
  51.     Public Const WA_PREVIOUS As Integer = 40044
  52.     Public Const WA_STOP As Integer = 40047
  53.     Public Const WA_VOLUME_DOWN As Integer = 40059
  54.     Public Const WA_VOLUME_UP As Integer = 40058
  55.  
  56. #End Region
  57.  
  58.     ' Declare our API calls.
  59.     Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
  60.     Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
  61.     Private Declare Function apiGetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Integer, ByVal sCaption As String, ByVal lCaptionSize As Integer) As Integer
  62.     Private Declare Function apiGetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Integer) As Integer
  63.  
  64.     Sub connect()
  65.         'I have no clue what the heck this stuff does.
  66.         'Stolen from MSDN's Socket stuff
  67.         Try
  68.             LIRCSocket.Connect(RemoteIP)
  69.         Catch
  70.  
  71.         End Try
  72.     End Sub
  73.  
  74.     Public Function Winamp_Hwnd() As Integer
  75.         ' Used to get the handle of the Winamp window.
  76.         Winamp_Hwnd = FindWindow("Winamp v1.x", Microsoft.VisualBasic.vbNullString)
  77.     End Function
  78.  
  79.     Public Function Foobar_Hwnd() As Integer
  80.         ' Used to get the handle of the Foobar2000 window.
  81.         Foobar_Hwnd = FindWindow("FOOBAR2000_CLASS", Microsoft.VisualBasic.vbNullString)
  82.     End Function
  83.  
  84.     Public Function GetWindowCaption(ByRef WhWnd As Integer) As String
  85.         'API WRAPPER TO GET WINDOW CAPTION INFO
  86.         Dim lLength As Integer
  87.         Dim sCaption As String
  88.         Dim lRetValue As Integer
  89.  
  90.         'Get length of windows Caption
  91.         lLength = apiGetWindowTextLength(WhWnd) + 1
  92.  
  93.         'Create a string of blanks to pass into apiGetWindowText
  94.         sCaption = New String(CType(" ", Char), lLength + 1)
  95.  
  96.         'Get Windows Caption
  97.         lRetValue = apiGetWindowText(WhWnd, sCaption, lLength)
  98.         GetWindowCaption = Microsoft.VisualBasic.Left(sCaption, lLength)
  99.     End Function
  100.  
  101.     Public Function ProcessSocket() As String
  102.         'this variable holds the string that will be received and stripped from the socket buffer thing
  103.         '        Dim SocketData As String
  104.         Dim BytesRec As Integer
  105.         BytesRec = LIRCSocket.Receive(mBytes)
  106.  
  107.         'assign what the remote program sent to a variable
  108.         ProcessSocket = (System.Text.Encoding.ASCII.GetString(mBytes, 0, 33))
  109.  
  110.         'This strips out the first 20 characters in the stuff recieved from the socket
  111.         ProcessSocket = ProcessSocket.Remove(0, 20)
  112.  
  113.         'This removes anything after the first 4 characters
  114.         ProcessSocket = ProcessSocket.Remove(4, (ProcessSocket.Length - 4))
  115.     End Function
  116.  
  117.     Function Foobar_Status() As String
  118.         Dim FoobarHandle As Integer
  119.         Dim FoobarTitle As String
  120.         FoobarHandle = Foobar_Hwnd()
  121.         FoobarTitle = GetWindowCaption(FoobarHandle)
  122.         If FoobarTitle.StartsWith("foobar2000") Then
  123.             Foobar_Status = "STOPPED"
  124.         Else
  125.             Foobar_Status = "PLAYING"
  126.         End If
  127.     End Function
  128.  
  129.  
  130.  
  131.     Sub main()
  132.         'Checks to see if the program is connected to the WinLIRC server
  133.         'if it isn't it creates a connection.
  134.         If mIsConnected = False Then
  135.             connect()
  136.             mIsConnected = True
  137.         End If
  138.  
  139.         Do Until mIsFinished = True
  140.  
  141.             Dim CommandData As String
  142.             Do Until CommandData <> ""
  143.                 CommandData = ProcessSocket()
  144.             Loop
  145.  
  146.             'holds the processed data from the winlirc socket
  147.  
  148.  
  149.             'Calls the function to process the data from the socket opened to the winlirc server
  150.             CommandData = ProcessSocket()
  151.  
  152.             'Holds the Command to send to the window
  153.             Dim WinampUserCommand As Integer
  154.  
  155.             Select Case CommandData
  156.                 Case Is = "play"
  157.                     'play/pause support could probably be implemented with more special handling
  158.                     'checking to see if foo is playing or not
  159.                     If Foobar_Status() = "PLAYING" Then
  160.                         If mFoobarPaused <> True Then
  161.                             WinampUserCommand = WA_PAUSE
  162.                             mFoobarPaused = True
  163.                         Else
  164.                             WinampUserCommand = WA_PAUSE
  165.                             mFoobarPaused = False
  166.                         End If
  167.                     Else
  168.                         WinampUserCommand = WA_PLAY
  169.                     End If
  170.                 Case Is = "stop"
  171.                     WinampUserCommand = WA_STOP
  172.                 Case Is = "next"
  173.                     WinampUserCommand = WA_NEXT
  174.                 Case Is = "back"
  175.                     WinampUserCommand = WA_PREVIOUS
  176.                 Case Is = "mute"
  177.                     'This case will require special handling to set the volume to 0 and then reset it to previous levels
  178.                     'Assuming it will work with foobar...
  179.                 Case Is = "volu"
  180.                     WinampUserCommand = WA_VOLUME_UP
  181.                 Case Is = "vold"
  182.                     WinampUserCommand = WA_VOLUME_DOWN
  183.                 Case Is = "+10 "
  184.                     WinampUserCommand = WA_STOP
  185.                     mIsFinished = True
  186.                 Case Else
  187.                     mIsFinished = True
  188.             End Select
  189.  
  190.             Call SendMessage(Winamp_Hwnd(), WM_COMMAND, WinampUserCommand, 0)
  191.  
  192.             Start = Microsoft.VisualBasic.DateAndTime.Timer
  193.             Finish = Start + 0.5  ' Set end time for 5-millisecond duration.
  194.             Do While Microsoft.VisualBasic.DateAndTime.Timer < Finish
  195.                 ' Do other processing while waiting for 5 seconds to elapse.
  196.             Loop
  197.  
  198.             CommandData = Microsoft.VisualBasic.vbNullString
  199.             WinampUserCommand = Microsoft.VisualBasic.vbNull
  200.  
  201.         Loop
  202.         Shutdown()
  203.     End Sub
  204.  
  205.     Sub Shutdown()
  206.         'This shuts down the socket and closes it like a good program
  207.         'It COULD crash so we use some exception handling
  208.         Try
  209.             LIRCSocket.Shutdown(System.Net.Sockets.SocketShutdown.Both)
  210.             LIRCSocket.Close()
  211.         Catch
  212.             'MsgBox("something really really bad happened when trying to close the socket...")
  213.         End Try
  214.     End Sub
  215. End Module