;__________________________________________________________ ;___________WinLIRC_Client_with_MacOSX_Volume_OSD__________ ;__________________Combined_by_gXpratama___________________ ;________________________060606____________________________ ; ; Wow, just realized it, i write my first scripts (well, ; combining with some adjustments actually, hehe.. :p) on ; June 06, 2006! Triple six! Wicked! Hehehe... :p Anyway, ; WinLIRC was taken from AutoHotKey Scripts Showcase, ; MacOSX Volume OSD was written by Landvermesser. Thx Man! ;__________________________________________________________ #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. SendMode Input ; Recommended for new scripts due to its superior speed and reliability. ;___________________________________________ ;__________WinLIRC_AHK_Autoexec_____________ ;___________________________________________ DelayBetweenButtonRepeats = 50 ; Specify the path to WinLIRC, such as C:\winlirc065\winlirc.exe WinLIRC_Path = %A_ProgramFiles%\winlirc065\winlirc.exe ; Specify WinLIRC's address and port. The most common are 127.0.0.1 (localhost) and 8765. WinLIRC_Address = 127.0.0.1 WinLIRC_Port = 8765 ;___________________________________________ ;_______MacOSX_Volume_OSD_Autoexec__________ ;___________________________________________ #Persistent IniRead, vol_Step, %A_SCRIPTDIR%\Finderbar_Engine.ini, SoundVolume, Step, 2 IniRead, vol_DisplayTime, %A_SCRIPTDIR%\Finderbar_Engine.ini, SoundVolume, DisplayTime, 2000 IniRead, vol_BackgroungPic, %A_SCRIPTDIR%\Finderbar_Engine.ini, SoundVolume, BackgroundPic IniRead, vol_Transparency, %A_SCRIPTDIR%\Finderbar_Engine.ini, SoundVolume, Transparency, 200 IniRead, vol_UpHotkey, %A_SCRIPTDIR%\Finderbar_Engine.ini, SoundVolume, VolumeUpHotkey, #Up IniRead, vol_DownHotkey, %A_SCRIPTDIR%\Finderbar_Engine.ini, SoundVolume, VolumeDownHotkey, #Down HotKey, %vol_UpHotkey%, vol_MasterUp HotKey, %vol_DownHotkey%, vol_MasterDown Menu,Tray, Add, Mute Sound, Mute Menu,Tray, Default, Mute Sound SetTimer, WatchSound, 500 ;return ; Do not change the following two lines. Skip them and continue below. Gosub WinLIRC_Init return ;_____________End_of_Autoexec_______________ ; -------------------------------------------- ; ASSIGN ACTIONS TO THE BUTTONS ON YOUR REMOTE ; -------------------------------------------- ; Configure your remote control's buttons below. Use WinLIRC's names ; for the buttons, which can be seen in your WinLIRC config file ; (.cf file) -- or you can press any button on your remote and the ; script will briefly display the button's name in a small window. ; ; Below are some examples. Feel free to revise or delete them to suit ; your preferences. sleep: Send, ^!q OSD("Goodbye!!!") return play: Send, ^!{insert} OSD("PLAY") return up: MouseMove, 0, -20, 0, R return down: MouseMove, 0, 20, 0, R return left: MouseMove, -20, 0, 0, R return right: MouseMove, 20, 0, 0, R return ok: Send, {lbutton} return vol+: Gosub, vol_MasterUp ; call MacOSX Volume function. return vol-: Gosub, vol_MasterDown ; call MacOSX Volume function. return muting: Gosub, Mute ; call MacOSX mute function. return ch+: Send, ^!{pgup} OSD("Previous Song") return ch-: Send, ^!{pgdn} OSD("Next Song") return recall: Send, !{tab} return ; The examples above give a feel for how to accomplish common tasks. ; To learn the basics of AutoHotkey, check out the Quick-start Tutorial ; at http://www.autohotkey.com/docs/Tutorial.htm ; ---------------------------- ; END OF CONFIGURATION SECTION ; ---------------------------- ; Do not make changes below this point unless you want to change the core ; functionality of the script. WinLIRC_Init: OnExit, ExitSub ; For connection cleanup purposes. ; Launch WinLIRC if it isn't already running: Process, Exist, winlirc.exe if not ErrorLevel ; No PID for WinLIRC was found. { IfNotExist, %WinLIRC_Path% { MsgBox The file "%WinLIRC_Path%" does not exist. Please edit this script to specify its location. ExitApp } Run %WinLIRC_Path% Sleep 200 ; Give WinLIRC a little time to initialize (probably never needed, just for peace of mind). } ; Connect to WinLIRC (or any type of server for that matter): socket := ConnectToAddress(WinLIRC_Address, WinLIRC_Port) if socket = -1 ; Connection failed (it already displayed the reason). ExitApp ; Find this script's main window: Process, Exist ; This sets ErrorLevel to this script's PID (it's done this way to support compiled scripts). DetectHiddenWindows On ScriptMainWindowId := WinExist("ahk_class AutoHotkey ahk_pid " . ErrorLevel) DetectHiddenWindows Off ; When the OS notifies the script that there is incoming data waiting to be received, ; the following causes a function to be launched to read the data: NotificationMsg = 0x5555 ; An arbitrary message number, but should be greater than 0x1000. OnMessage(NotificationMsg, "ReceiveData") ; Set up the connection to notify this script via message whenever new data has arrived. ; This avoids the need to poll the connection and thus cuts down on resource usage. FD_READ = 1 ; Received when data is available to be read. FD_CLOSE = 32 ; Received when connection has been closed. if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", NotificationMsg, "Int", FD_READ|FD_CLOSE) { MsgBox % "WSAAsyncSelect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") ExitApp } return ConnectToAddress(IPAddress, Port) ; This can connect to most types of TCP servers, not just WinLIRC. ; Returns -1 (INVALID_SOCKET) on failure or the socket ID upon success. { VarSetCapacity(wsaData, 32) ; The struct is only about 14 in size, so 32 is conservative. result := DllCall("Ws2_32\WSAStartup", "UShort", 0x0002, "UInt", &wsaData) ; Request Winsock 2.0 (0x0002) ; Since WSAStartup() will likely be the first Winsock function called by this script, ; check ErrorLevel to see if the OS has Winsock 2.0 available: if ErrorLevel { MsgBox WSAStartup() could not be called due to error %ErrorLevel%. Winsock 2.0 or higher is required. return -1 } if result ; Non-zero, which means it failed (most Winsock functions return 0 on success). { MsgBox % "WSAStartup() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") return -1 } AF_INET = 2 SOCK_STREAM = 1 IPPROTO_TCP = 6 socket := DllCall("Ws2_32\socket", "Int", AF_INET, "Int", SOCK_STREAM, "Int", IPPROTO_TCP) if socket = -1 { MsgBox % "socket() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") return -1 } ; Prepare for connection: SizeOfSocketAddress = 16 VarSetCapacity(SocketAddress, SizeOfSocketAddress) InsertInteger(2, SocketAddress, 0, AF_INET) ; sin_family InsertInteger(DllCall("Ws2_32\htons", "UShort", Port), SocketAddress, 2, 2) ; sin_port InsertInteger(DllCall("Ws2_32\inet_addr", "Str", IPAddress), SocketAddress, 4, 4) ; sin_addr.s_addr ; Attempt connection: if DllCall("Ws2_32\connect", "UInt", socket, "UInt", &SocketAddress, "Int", SizeOfSocketAddress) { MsgBox % "connect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") . ". Is WinLIRC running?" return -1 } return socket ; Indicate success by returning a valid socket ID rather than -1. } ReceiveData(wParam, lParam) ; By means of OnMessage(), this function has been set up to be called automatically whenever new data ; arrives on the connection. It reads the data from WinLIRC and takes appropriate action depending ; on the contents. { socket := wParam ReceivedDataSize = 4096 ; Large in case a lot of data gets buffered due to delay in processing previous data. Loop ; This loop solves the issue of the notification message being discarded due to thread-already-running. { VarSetCapacity(ReceivedData, ReceivedDataSize, 0) ; 0 for last param terminates string for use with recv(). ReceivedDataLength := DllCall("Ws2_32\recv", "UInt", socket, "Str", ReceivedData, "Int", ReceivedDataSize, "Int", 0) if ReceivedDataLength = 0 ; The connection was gracefully closed, probably due to exiting WinLIRC. ExitApp ; The OnExit routine will call WSACleanup() for us. if ReceivedDataLength = -1 { WinsockError := DllCall("Ws2_32\WSAGetLastError") if WinsockError = 10035 ; WSAEWOULDBLOCK, which means "no more data to be read". return 1 if WinsockError <> 10054 ; WSAECONNRESET, which happens when WinLIRC closes via system shutdown/logoff. ; Since it's an unexpected error, report it. Also exit to avoid infinite loop. MsgBox % "recv() indicated Winsock error " . WinsockError ExitApp ; The OnExit routine will call WSACleanup() for us. } ; Otherwise, process the data received. Testing shows that it's possible to get more than one line ; at a time (even for explicitly-sent IR signals), which the following method handles properly. ; Data received from WinLIRC looks like the following example (see the WinLIRC docs for details): ; 0000000000eab154 00 NameOfButton NameOfRemote Loop, parse, ReceivedData, `n, `r { if A_LoopField in ,BEGIN,SIGHUP,END ; Ignore blank lines and WinLIRC's start-up messages. continue ButtonName = ; Init to blank in case there are less than 3 fields found below. Loop, parse, A_LoopField, %A_Space% ; Extract the button name, which is the third field. if A_Index = 3 ButtonName := A_LoopField global DelayBetweenButtonRepeats ; Declare globals to make them available to this function. static PrevButtonName, PrevButtonTime, RepeatCount ; These variables remember their values between calls. if (ButtonName != PrevButtonName || A_TickCount - PrevButtonTime > DelayBetweenButtonRepeats) { if IsLabel(ButtonName) ; There is a subroutine associated with this button. Gosub %ButtonName% ; Launch the subroutine. else ; Since there is no associated subroutine, briefly display which button was pressed. { if (ButtonName == PrevButtonName) RepeatCount += 1 else RepeatCount = 1 SplashTextOn, 150, 20, Button from WinLIRC, %ButtonName% (%RepeatCount%) SetTimer, SplashOff, 3000 ; This allows more signals to be processed while displaying the window. } PrevButtonName := ButtonName PrevButtonTime := A_TickCount } } } return 1 ; Tell the program that no further processing of this message is needed. } SplashOff: SplashTextOff SetTimer, SplashOff, Off return InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4) ; To preserve any existing contents in pDest, only pSize number of bytes starting at pOffset ; are altered in it. The caller must ensure that pDest has sufficient capacity. { mask := 0xFF ; This serves to isolate each byte, one by one. Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data. { DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index - 1, "UInt", 1 ; Write one byte. , "UChar", (pInteger & mask) >> 8 * (A_Index - 1)) mask := mask << 8 ; Set it up for isolation of the next byte. } } ExitSub: ; This subroutine is called automatically when the script exits for any reason. ; MSDN: "Any sockets open when WSACleanup is called are reset and automatically ; deallocated as if closesocket was called." DllCall("Ws2_32\WSACleanup") ExitApp ;______________________________________________________ ;___________MacOSX_Volume_OSD_Scripts__________________ ;______________________________________________________ Mute: SoundSet, +0, , Mute Return WatchSound: SoundGet, vol_Mute, , Mute If vol_Mute = On { Menu, Tray, Check, Mute Sound Menu, Tray, Icon, %A_ScriptDir%\images\Volume4.ico Return } IfEqual, vol_Mute, Off, Menu, Tray, Uncheck, Mute Sound SoundGet, vol_Master, Master If vol_Master < 1 Menu, Tray, Icon, %A_ScriptDir%\images\Volume0.ico If vol_Master between 1 and 20 Menu, Tray, Icon, %A_ScriptDir%\images\Volume1.ico If vol_Master between 20 and 50 Menu, Tray, Icon, %A_ScriptDir%\images\Volume2.ico If vol_Master > 50 Menu, Tray, Icon, %A_ScriptDir%\images\Volume3.ico Return vol_ShowBars: IfWinNotExist, %A_ScriptName% { Gui, 3:Add, Pic, x0 y0 w213 h208, %A_ScriptDir%\images\background.gif Gui, 3:Add, Progress, x35 y160 w144 h12 -Smooth, 50 Gui, 3:+ToolWindow DetectHiddenWindows, On WinWait, %A_ScriptName% WinSet, TransColor,0000FF %vol_Transparency% WinSet, AlwaysOnTop, On, %A_ScriptName% Gui, 3:-Caption Gui, 3:Show, h208 w213 } SoundGet, vol_Master, Master GuiControl, 3:, msctls_progress321, %vol_Master% SoundPlay, %A_ScriptDir%\images\sound.wav SetTimer, vol_BarOff, %vol_DisplayTime% Return vol_BarOff: transparent =%vol_Transparency% SetTimer, vol_BarOff, off Loop, %transparent% { transparent -= 1 WinSet, TransColor, 0000FF %transparent%, %A_ScriptName% } Gui, 3:Destroy Return vol_MasterUp: SoundSet, +%vol_Step% Gosub, vol_ShowBars Return vol_MasterDown: SoundSet, -%vol_Step% Gosub, vol_ShowBars Return ;______________________________________________________ ;_____________________OSD_Scripts______________________ ;______________________________________________________ OSD(MyText) { CustomColor = 00FE00 ; Can be any RGB color (it will be made transparent below). Gui, +AlwaysOnTop +LastFound +Owner ; +Owner prevents a taskbar button from appearing. Gui, Color, %CustomColor% Gui, Font, s36 wBold, Arial Gui, Add, Text, cLime, %MyText% Gui, -Caption ; Remove the title bar and window borders. ; Make all pixels of this color transparent and make the text itself translucent (150): WinSet, TransColor, %CustomColor% 150 SetTimer, RemoveOSD, 800 Gui, Show, Center return RemoveOSD: SetTimer, RemoveOSD, Off Gui, Destroy return } ;__________________________________________ ;_____________End_of_Scripts_______________ ;__________________________________________
WinLIRC Client + MacOSX Volume + OSD
Started by
gXpratama
, Jun 08 2006 08:51 AM
No replies to this topic
Hi all.. I just use AHK for several days and find it really cool! As a newbie, I try to combine several scripts available to suit my needs.. And here it is, as I use WinLIRC to control my computer using a remote controller, I also want the scripts to show that MacOSX-style-volume-control OSD when I press volume button in my remote controller, and an ordinary OSD displaying name of the function for other buttons. Here's the script, and yes I realized that this script is bloated. Maybe someone could help me to learn AHK better and/or give comments how to optimize the script? Thx in advance..
#1
-
Posted 08 June 2006 - 08:51 AM
[gXpratama]