PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/AutoHotkey.docset/Contents/Resources/Documents/scripts/WinLIRC.htm

https://gitlab.com/ahkscript/Autohotkey.docset
HTML | 297 lines | 256 code | 41 blank | 0 comment | 0 complexity | cf67d1faae4eff403840ccac954ea3b0 MD5 | raw file
  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <title>WinLIRC Client</title>
  5. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  6. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  7. <link href="../static/theme.css" rel="stylesheet" type="text/css" />
  8. <script src="../static/content.js" type="text/javascript"></script>
  9. <meta name="description" content="This open-source WinLIRC client can perform keystrokes, mouse clicks, and other actions in response to buttons you press on your remote control.">
  10. </head>
  11. <body>
  12. <h1>WinLIRC Client</h1>
  13. <p>This script receives notifications from <a href="http://winlirc.sourceforge.net">WinLIRC</a> whenever you press
  14. a button on your remote control. It can be used to automate Winamp,
  15. Windows Media Player, etc. It's easy to configure. For example, if
  16. WinLIRC recognizes a button named &quot;VolUp&quot; on your remote control,
  17. create a label named VolUp and beneath it use the command
  18. <code>SoundSet +5</code> to increase the soundcard's volume by 5%.
  19. </p>
  20. <p><a href="WinLIRC.ahk">Download This Script</a> &nbsp;| &nbsp;<a href="index.htm">Other Sample Scripts</a> &nbsp;| &nbsp;<a href="../AutoHotkey.htm">Home</a></p>
  21. <pre class="NoIndent"><em>; Here are the steps to use this script:
  22. ; 1) Configure WinLIRC to recognize your remote control and its buttons.
  23. ; WinLIRC is at <a href="http://winlirc.sourceforge.net">http://winlirc.sourceforge.net</a>
  24. ; 2) Edit the WinLIRC path, address, and port in the CONFIG section below.
  25. ; 3) Launch this script. It will start the WinLIRC server if needed.
  26. ; 4) Press some buttons on your remote control. A small window will
  27. ; appear showing the name of each button as you press it.
  28. ; 5) Configure your buttons to send keystrokes and mouse clicks to
  29. ; windows such as Winamp, Media Player, etc. See the examples below.</em>
  30. <em>; This script requires AutoHotkey 1.0.38.04 or later.
  31. ; HISTORY OF CHANGES
  32. ; March 2, 2007:
  33. ; - Improved reliability via &quot;Critical&quot; in ReceiveData().
  34. ; October 5, 2005:
  35. ; - Eliminated Winsock warning dialog &quot;10054&quot; upon system shutdown/logoff.
  36. ; - Added option &quot;DelayBetweenButtonRepeats&quot; to throttle the repeat speed.</em>
  37. <em>; -------------------------------------------------
  38. ; CONFIGURATION SECTION: Set your preferences here.
  39. ; -------------------------------------------------
  40. ; Some remote controls repeat the signal rapidly while you're holding down
  41. ; a button. This makes it difficult to get the remote to send only a single
  42. ; signal. The following setting solves this by ignoring repeated signals
  43. ; until the specified time has passed. 200 is often a good setting. Set it
  44. ; to 0 to disable this feature.</em>
  45. DelayBetweenButtonRepeats = 200
  46. <em>; Specify the path to WinLIRC, such as C:\WinLIRC\winlirc.exe</em>
  47. WinLIRC_Path = %A_ProgramFiles%\WinLIRC\winlirc.exe
  48. <em>; Specify WinLIRC's address and port. The most common are 127.0.0.1 (localhost) and 8765.</em>
  49. WinLIRC_Address = 127.0.0.1
  50. WinLIRC_Port = 8765
  51. <em>; Do not change the following two lines. Skip them and continue below.</em>
  52. Gosub WinLIRC_Init
  53. return
  54. <em>; --------------------------------------------
  55. ; ASSIGN ACTIONS TO THE BUTTONS ON YOUR REMOTE
  56. ; --------------------------------------------
  57. ; Configure your remote control's buttons below. Use WinLIRC's names
  58. ; for the buttons, which can be seen in your WinLIRC config file
  59. ; (.cf file) -- or you can press any button on your remote and the
  60. ; script will briefly display the button's name in a small window.
  61. ;
  62. ; Below are some examples. Feel free to revise or delete them to suit
  63. ; your preferences.</em>
  64. VolUp:
  65. SoundSet +5 <em>; Increase master volume by 5%. On Vista, replace this line with: Send {Volume_Up}</em>
  66. return
  67. VolDown:
  68. SoundSet -5 <em>; Reduce master volume by 5%. On Vista, replace this line with: Send {Volume_Down}</em>
  69. return
  70. ChUp:
  71. WinGetClass, ActiveClass, A
  72. if ActiveClass in Winamp v1.x,Winamp PE <em>; Winamp is active.</em>
  73. Send {right} <em>; Send a right-arrow keystroke.</em>
  74. else <em>; Some other type of window is active.</em>
  75. Send {WheelUp} <em>; Rotate the mouse wheel up by one notch.</em>
  76. return
  77. ChDown:
  78. WinGetClass, ActiveClass, A
  79. if ActiveClass in Winamp v1.x,Winamp PE <em>; Winamp is active.</em>
  80. Send {left} <em>; Send a left-arrow keystroke.</em>
  81. else <em>; Some other type of window is active.</em>
  82. Send {WheelDown} <em>; Rotate the mouse wheel down by one notch.</em>
  83. return
  84. Menu:
  85. IfWinExist, Untitled - Notepad
  86. {
  87. WinActivate
  88. }
  89. else
  90. {
  91. Run, Notepad
  92. WinWait, Untitled - Notepad
  93. WinActivate
  94. }
  95. Send Here are some keystrokes sent to Notepad.{Enter}
  96. return
  97. <em>; The examples above give a feel for how to accomplish common tasks.
  98. ; To learn the basics of AutoHotkey, check out the Quick-start Tutorial
  99. ; at <a href="http://www.autohotkey.com/docs/Tutorial.htm">http://www.autohotkey.com/docs/Tutorial.htm</a></em>
  100. <em>; ----------------------------
  101. ; END OF CONFIGURATION SECTION
  102. ; ----------------------------
  103. ; Do not make changes below this point unless you want to change the core
  104. ; functionality of the script.</em>
  105. WinLIRC_Init:
  106. OnExit, ExitSub <em>; For connection cleanup purposes.</em>
  107. <em>; Launch WinLIRC if it isn't already running:</em>
  108. Process, Exist, winlirc.exe
  109. if not ErrorLevel <em>; No PID for WinLIRC was found.</em>
  110. {
  111. IfNotExist, %WinLIRC_Path%
  112. {
  113. MsgBox The file &quot;%WinLIRC_Path%&quot; does not exist. Please edit this script to specify its location.
  114. ExitApp
  115. }
  116. Run %WinLIRC_Path%
  117. Sleep 200 <em>; Give WinLIRC a little time to initialize (probably never needed, just for peace of mind).</em>
  118. }
  119. <em>; Connect to WinLIRC (or any type of server for that matter):</em>
  120. socket := ConnectToAddress(WinLIRC_Address, WinLIRC_Port)
  121. if socket = -1 <em>; Connection failed (it already displayed the reason).</em>
  122. ExitApp
  123. <em>; Find this script's main window:</em>
  124. Process, Exist <em>; This sets ErrorLevel to this script's PID (it's done this way to support compiled scripts).</em>
  125. DetectHiddenWindows On
  126. ScriptMainWindowId := WinExist(&quot;ahk_class AutoHotkey ahk_pid &quot; . ErrorLevel)
  127. DetectHiddenWindows Off
  128. <em>; When the OS notifies the script that there is incoming data waiting to be received,
  129. ; the following causes a function to be launched to read the data:</em>
  130. NotificationMsg = 0x5555 <em>; An arbitrary message number, but should be greater than 0x1000.</em>
  131. OnMessage(NotificationMsg, &quot;ReceiveData&quot;)
  132. <em>; Set up the connection to notify this script via message whenever new data has arrived.
  133. ; This avoids the need to poll the connection and thus cuts down on resource usage.</em>
  134. FD_READ = 1 <em>; Received when data is available to be read.</em>
  135. FD_CLOSE = 32 <em>; Received when connection has been closed.</em>
  136. if DllCall(&quot;Ws2_32\WSAAsyncSelect&quot;, &quot;UInt&quot;, socket, &quot;UInt&quot;, ScriptMainWindowId, &quot;UInt&quot;, NotificationMsg, &quot;Int&quot;, FD_READ|FD_CLOSE)
  137. {
  138. MsgBox % &quot;WSAAsyncSelect() indicated Winsock error &quot; . DllCall(&quot;Ws2_32\WSAGetLastError&quot;)
  139. ExitApp
  140. }
  141. return
  142. ConnectToAddress(IPAddress, Port)
  143. <em>; This can connect to most types of TCP servers, not just WinLIRC.
  144. ; Returns -1 (INVALID_SOCKET) upon failure or the socket ID upon success.</em>
  145. {
  146. VarSetCapacity(wsaData, 400)
  147. result := DllCall(&quot;Ws2_32\WSAStartup&quot;, &quot;UShort&quot;, 0x0002, &quot;UInt&quot;, &amp;wsaData) <em>; Request Winsock 2.0 (0x0002)</em>
  148. <em>; Since WSAStartup() will likely be the first Winsock function called by this script,</em>
  149. <em>; check ErrorLevel to see if the OS has Winsock 2.0 available:</em>
  150. if ErrorLevel
  151. {
  152. MsgBox WSAStartup() could not be called due to error %ErrorLevel%. Winsock 2.0 or higher is required.
  153. return -1
  154. }
  155. if result <em>; Non-zero, which means it failed (most Winsock functions return 0 upon success).</em>
  156. {
  157. MsgBox % &quot;WSAStartup() indicated Winsock error &quot; . DllCall(&quot;Ws2_32\WSAGetLastError&quot;)
  158. return -1
  159. }
  160. AF_INET = 2
  161. SOCK_STREAM = 1
  162. IPPROTO_TCP = 6
  163. socket := DllCall(&quot;Ws2_32\socket&quot;, &quot;Int&quot;, AF_INET, &quot;Int&quot;, SOCK_STREAM, &quot;Int&quot;, IPPROTO_TCP)
  164. if socket = -1
  165. {
  166. MsgBox % &quot;socket() indicated Winsock error &quot; . DllCall(&quot;Ws2_32\WSAGetLastError&quot;)
  167. return -1
  168. }
  169. <em>; Prepare for connection:</em>
  170. SizeOfSocketAddress = 16
  171. VarSetCapacity(SocketAddress, SizeOfSocketAddress)
  172. InsertInteger(2, SocketAddress, 0, AF_INET) <em>; sin_family</em>
  173. InsertInteger(DllCall(&quot;Ws2_32\htons&quot;, &quot;UShort&quot;, Port), SocketAddress, 2, 2) <em>; sin_port</em>
  174. InsertInteger(DllCall(&quot;Ws2_32\inet_addr&quot;, &quot;AStr&quot;, IPAddress), SocketAddress, 4, 4) <em>; sin_addr.s_addr</em>
  175. <em>; Attempt connection:</em>
  176. if DllCall(&quot;Ws2_32\connect&quot;, &quot;UInt&quot;, socket, &quot;UInt&quot;, &amp;SocketAddress, &quot;Int&quot;, SizeOfSocketAddress)
  177. {
  178. MsgBox % &quot;connect() indicated Winsock error &quot; . DllCall(&quot;Ws2_32\WSAGetLastError&quot;) . &quot;. Is WinLIRC running?&quot;
  179. return -1
  180. }
  181. return socket <em>; Indicate success by returning a valid socket ID rather than -1.</em>
  182. }
  183. ReceiveData(wParam, lParam)
  184. <em>; By means of OnMessage(), this function has been set up to be called automatically whenever new data
  185. ; arrives on the connection. It reads the data from WinLIRC and takes appropriate action depending
  186. ; on the contents.</em>
  187. {
  188. Critical <em>; Prevents another of the same message from being discarded due to thread-already-running.</em>
  189. socket := wParam
  190. ReceivedDataSize = 4096 <em>; Large in case a lot of data gets buffered due to delay in processing previous data.</em>
  191. VarSetCapacity(ReceivedData, ReceivedDataSize, 0) <em>; 0 for last param terminates string for use with recv().</em>
  192. ReceivedDataLength := DllCall(&quot;Ws2_32\recv&quot;, &quot;UInt&quot;, socket, &quot;Str&quot;, ReceivedData, &quot;Int&quot;, ReceivedDataSize, &quot;Int&quot;, 0)
  193. if ReceivedDataLength = 0 <em>; The connection was gracefully closed, probably due to exiting WinLIRC.</em>
  194. ExitApp <em>; The OnExit routine will call WSACleanup() for us.</em>
  195. if ReceivedDataLength = -1
  196. {
  197. WinsockError := DllCall(&quot;Ws2_32\WSAGetLastError&quot;)
  198. if WinsockError = 10035 <em>; WSAEWOULDBLOCK, which means &quot;no more data to be read&quot;.</em>
  199. return 1
  200. if WinsockError &lt;&gt; 10054 <em>; WSAECONNRESET, which happens when WinLIRC closes via system shutdown/logoff.</em>
  201. <em>; Since it's an unexpected error, report it. Also exit to avoid infinite loop.</em>
  202. MsgBox % &quot;recv() indicated Winsock error &quot; . WinsockError
  203. ExitApp <em>; The OnExit routine will call WSACleanup() for us.</em>
  204. }
  205. <em>; Otherwise, process the data received. Testing shows that it's possible to get more than one line</em>
  206. <em>; at a time (even for explicitly-sent IR signals), which the following method handles properly.</em>
  207. <em>; Data received from WinLIRC looks like the following example (see the WinLIRC docs for details):</em>
  208. <em>; 0000000000eab154 00 NameOfButton NameOfRemote</em>
  209. Loop, parse, ReceivedData, `n, `r
  210. {
  211. if A_LoopField in ,BEGIN,SIGHUP,END <em>; Ignore blank lines and WinLIRC's start-up messages.</em>
  212. continue
  213. ButtonName = <em>; Init to blank in case there are less than 3 fields found below.</em>
  214. Loop, parse, A_LoopField, %A_Space% <em>; Extract the button name, which is the third field.</em>
  215. if A_Index = 3
  216. ButtonName := A_LoopField
  217. global DelayBetweenButtonRepeats <em>; Declare globals to make them available to this function.</em>
  218. static PrevButtonName, PrevButtonTime, RepeatCount <em>; These variables remember their values between calls.</em>
  219. if (ButtonName != PrevButtonName || A_TickCount - PrevButtonTime &gt; DelayBetweenButtonRepeats)
  220. {
  221. if IsLabel(ButtonName) <em>; There is a subroutine associated with this button.</em>
  222. Gosub %ButtonName% <em>; Launch the subroutine.</em>
  223. else <em>; Since there is no associated subroutine, briefly display which button was pressed.</em>
  224. {
  225. if (ButtonName == PrevButtonName)
  226. RepeatCount += 1
  227. else
  228. RepeatCount = 1
  229. SplashTextOn, 150, 20, Button from WinLIRC, %ButtonName% (%RepeatCount%)
  230. SetTimer, SplashOff, 3000 <em>; This allows more signals to be processed while displaying the window.</em>
  231. }
  232. PrevButtonName := ButtonName
  233. PrevButtonTime := A_TickCount
  234. }
  235. }
  236. return 1 <em>; Tell the program that no further processing of this message is needed.</em>
  237. }
  238. SplashOff:
  239. SplashTextOff
  240. SetTimer, SplashOff, Off
  241. return
  242. InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
  243. <em>; The caller must ensure that pDest has sufficient capacity. To preserve any existing contents in pDest,
  244. ; only pSize number of bytes starting at pOffset are altered in it.</em>
  245. {
  246. Loop %pSize% <em>; Copy each byte in the integer into the structure as raw binary data.</em>
  247. DllCall(&quot;RtlFillMemory&quot;, &quot;UInt&quot;, &amp;pDest + pOffset + A_Index-1, &quot;UInt&quot;, 1, &quot;UChar&quot;, pInteger &gt;&gt; 8*(A_Index-1) &amp; 0xFF)
  248. }
  249. ExitSub: <em>; This subroutine is called automatically when the script exits for any reason.
  250. ; MSDN: &quot;Any sockets open when WSACleanup is called are reset and automatically
  251. ; deallocated as if closesocket was called.&quot;</em>
  252. DllCall(&quot;Ws2_32\WSACleanup&quot;)
  253. ExitApp
  254. </pre>
  255. </body>
  256. </html>