... Вдруг мысль пришла: а что если попробовать повесить эти три кнопки не на клаву, а напрямую - на кнопки IR пульта?
Я ведь управление настраиваю тоже на AHK - WinLIRC Client, взятый из стандартной справки ... получается двойная эмуляция.
Возможно и заработает .... вот только как это лучше сделать? Может есть мысли?
Выложу свой вариант WinLIRC Client адаптированный к AVerLIRC ( тот-же WinLIRC для тюнеров AVer )
#NoEnv
SendMode Input
; Запуск программы от имени Админа
If not A_IsAdmin
{
Run *RunAs "%A_ScriptFullPath%"
ExitApp
}
Process, Priority,, HIGH ; Установить приоритет процесса скрипта в High (высокий).
DelayBetweenButtonRepeats = 200
; Specify AVerLIRC's address and port. The most common are 127.0.0.1 (localhost) and 8765.
AVerLIRC_Address = 127.0.0.1
AVerLIRC_Port = 666
; Do not change the following two lines. Skip them and continue below.
Gosub AVerLIRC_Init
return
; ----------------------------------------------------
; Назначение действий для кнопок пульта AVerMedia-H831
; ----------------------------------------------------
; J.River Media Center
;--------------------------------------------------
Source:
return
;--------------------------------------------------
Power:
Run, OSD-RemoteMenu.ahk
return
;--------------------------------------------------
Full_screen:
Run, mc19.exe /mcc 22000`,2
GoTo UpdateTime
return
;--------------------------------------------------
Record:
Send {vk26} ; <Up>
;Run, mc19.exe /mcc 27000`,38
return
;--------------------------------------------------
; Кнопка для всех программ
Audio:
Process, Exist, Watch.exe
{
If ! ErrorLevel
{
Run, Watch.exe
}
Else
{
Process, Close, Watch.exe
}
}
return
;--------------------------------------------------
Rewind:
Run, mc19.exe /mcc 27000`,37
return
;--------------------------------------------------
Play/Pause:
Send {vkD} ; <Enter>
;Run, mc19.exe /mcc 27000`,13
return
;--------------------------------------------------
Forward:
Run, mc19.exe /mcc 27000`,39
return
;--------------------------------------------------
Display:
Run, mc19.exe /mcc 10009
return
;--------------------------------------------------
Stop:
Send {vk28} ; <Down>
;Run, mc19.exe /mcc 27000`,40
return
;--------------------------------------------------
EPG:
Run, mc19.exe /mcc 10008
return
;--------------------------------------------------
; Кнопка для всех программ
Vol+:
Send {vkAF}
SoundSet +2
return
;--------------------------------------------------
Ch+:
Run, mc19.exe /mcc 10003
return
;--------------------------------------------------
; Кнопка для всех программ
Vol-:
Send {vkAE}
SoundSet -2
return
;--------------------------------------------------
Ch-:
Run, mc19.exe /mcc 10004
return
;--------------------------------------------------
1:
Run, mc19.exe /mcc 27000`,97
return
;--------------------------------------------------
2:
Run, mc19.exe /mcc 27000`,98
return
;--------------------------------------------------
3:
Run, mc19.exe /mcc 27000`,99
return
;--------------------------------------------------
4:
Run, mc19.exe /mcc 27000`,100
return
;--------------------------------------------------
5:
Run, mc19.exe /mcc 27000`,101
return
;--------------------------------------------------
6:
Run, mc19.exe /mcc 27000`,102
return
;--------------------------------------------------
7:
Run, mc19.exe /mcc 27000`,103
return
;--------------------------------------------------
8:
Run, mc19.exe /mcc 27000`,104
return
;--------------------------------------------------
9:
Run, mc19.exe /mcc 27000`,105
return
;--------------------------------------------------
Ch_Return:
return
;--------------------------------------------------
0:
Run, mc19.exe /mcc 27000`,96
return
;--------------------------------------------------
; Кнопка для всех программ
Mute:
Send {vkAD}
return
;--------------------------------------------------
; Sub - обновление часов
UpdateTime:
Process, Exist, Watch.exe
{
If ErrorLevel
{
Process, Close, Watch.exe
Sleep, 500
Run, Watch.exe
}
}
return
;--------------------------------------------------
; ----------------------------
; END OF CONFIGURATION SECTION
; ----------------------------
; Do not make changes below this point unless you want to change the core
; functionality of the script.
AVerLIRC_Init:
OnExit, ExitSub ; For connection cleanup purposes.
; Launch AVerLIRC if it isn't already running:
Process, Exist, averlirc.exe
if ! ErrorLevel ; No PID for AVerLIRC was found.
{
MsgBox, 0x30, AVerLIRC Client, Похоже`, AVerLIRC не запущен.`n`nПытаюсь подключить сервер., 2
RunWait, net start averlirc, , Hide
}
; Connect to AVerLIRC (or any type of server for that matter):
socket := ConnectToAddress(AVerLIRC_Address, AVerLIRC_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 AVerLIRC.
; Returns -1 (INVALID_SOCKET) upon failure or the socket ID upon success.
{
VarSetCapacity(wsaData, 400)
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 upon 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 AVerLIRC 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 AVerLIRC and takes appropriate action depending
; on the contents.
{
Critical ; Prevents another of the same message from being discarded due to thread-already-running.
socket := wParam
ReceivedDataSize = 4096 ; Large in case a lot of data gets buffered due to delay in processing previous data.
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 AVerLIRC.
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 AVerLIRC 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 AVerLIRC looks like the following example (see the AVerLIRC docs for details):
; 0000000000eab154 00 NameOfButton NameOfRemote
Loop, parse, ReceivedData, `n, `r
{
if A_LoopField in ,BEGIN,SIGHUP,END ; Ignore blank lines and AVerLIRC'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 AVerLIRC, %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)
; The caller must ensure that pDest has sufficient capacity. To preserve any existing contents in pDest,
; only pSize number of bytes starting at pOffset are altered in it.
{
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, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}
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
Может здесь лучше использовать #Include OSD-RemoteMenu.ahk или непосредственно "вшить" в этот скрипт? Какие предложения?
... Собсна, названия кнопок, на которые надо повесить, с закомментированными названиями клавиш.