Тема: AutoHotkey: Управление Foobar'ом
Вот здесь я выкладывал скрипт по управлению WinAmp'ом. С тех пор я пересел на Foobar. Однако управлять им скриптами не так удобно, как WinAmp'ом. В частности, он не понимает SendMessage/PostMessage, а управляется из командной строки. Такое управление имеет недостаток: нужно знать полный путь к Foobar'у. А если вы изменили его расположение? Или запустили свой управляющий скрипт на чужой машине, где Foobar есть, но путь у него другой? Или вот у меня два Foobar'а, один - тестовый, где я отлаживаю его вид, тестирую плагины и прочее (это особенность Foobar'а: он очень гибко настраивается, но делать это непросто), а другой - уже настроенный, постоянный. И пути у них, разумеется, разные. Вот для того, чтобы можно было управлять Foobar'ом независимо от того, откуда он запущен я и написал предлагаемую функцию:
;-------------------------------------------------------------------------------
FooBarControl( fooCommand ) ; функция управления foobar'ом
{
; В качестве параметра функция принимает параметр ком. строки foobar'а (без слеша)
BatchLines_Before := A_BatchLines ; запоминаем текущие настройки скорости выполнения скрипта
SetBatchLines, -1 ; указываем максимальную скорость для скрипта
Process, Exist, foobar2000.exe ; проверяем существование процесса foobar2000
Foo_PID := ErrorLevel ; вносим PID в переменную
If NOT Foo_PID ; если процесс не существует, то...
Return ; выйти из функции
; если процесс существует, то продолжаем...
h_process := DllCall( "OpenProcess" ; открываем хендл процесса (права будут нужны для GetModuleFileNameExA)
, "UInt", 0x10|0x400 ; с нужными правами: 0x10 = PROCESS_VM_READ, 0x400 = PROCESS_QUERY_INFORMATION
, "Int" , False ; без наследования хендла
, "UInt", Foo_PID ) ; для указанного PID'а
If ( ErrorLevel OR h_process = 0 ) ; если почему-либо не удалось открыть хендл (или он открыт для несуществующего PID'а)...
Goto, fbc_Return ; перейти к закрытию хендла и выйти из функции
VarSetCapacity( FooExePath, 255 ) ; обеспечиваем достаточную вместимость переменной (путь в символах, длиннее не бывает)
DllCall( "psapi.dll\GetModuleFileNameExA" ; получаем путь к исполнимому файлу процесса GetModuleFileNameExA-(ANSI)
, "UInt", h_process ; для указанного хендла процесса
, "UInt", 0 ; нас интересует не модуль, а целиком процесс
, "Str" , FooExePath ; переменная, получающая путь
, "UInt", 255 ) ; 255 - длина извлекаемого пути в символах (длиннее не бывает)
fbc_Return: ; метка перехода к закрытию хендла процесса
DllCall( "CloseHandle", "UInt", h_process ) ; закрываем хендл процесса
RunWait, %FooExePath% /"%fooCommand%" ; отправить команду foobar'у (и дождаться её выполнения)
SetBatchLines, %BatchLines_Before% ; восстанавливаем скорость скрипта
Return ; выйти из функции
} ; конец функции
;-------------------------------------------------------------------------------
А вот скрипт, использующий эту функцию и содержащий самые главные, на мой взгляд, команды Foobar'а (скрипт можно забрать архивом):
;*******************************************************************************
; AutoHotkey Version: 1.0.44.09+
; Автор: Androgen Belkin
; Имя скрипта: FooBarControl().ahk (v.1.0)
;*******************************************************************************
; Управление Foobar'ом.
;*******************************************************************************
;~ #NoTrayIcon ; не отображать значок скрипта в трее
#SingleInstance force ; перезагрузить скрипт, если он уже запущен
#NoEnv ; запрещаем имена переменных как у переменных окружения
SendMode Input ; новый режим высылки без задержки и повышенной надежности
; ========== НАСТРОЙКИ ПОЛЬЗОВАТЕЛЯ ===============
Foobar_Path = D:\Program_2\Foobar\foobar2000.exe
; ========== КОНЕЦ НАСТРОЕК ПОЛЬЗОВАТЕЛЯ ==========
; высылать эти клавиши всегда, кроме тех случаев,
; когда они используется в горячих клавишах
$Numpad0:: Send, {Numpad0} ; высылать Numpad0
$NumpadIns:: Send, {NumpadIns} ; высылать NumpadIns
; ========== ЗАПУСТИТЬ Foobar ==========
;-------------------------------------------------------------------------------
NumpadIns & NumpadEnter:: ; запустить Foobar
Numpad0 & NumpadEnter:: ; запустить Foobar
Launch_Media:: ; обработка мультимедийной клавы
;-------------------------------------------------------------------------------
IfNotExist, %Foobar_Path% ; если НЕ существует указанный файл для запуска
Return ; закончить обработку горячей клавиши
; если путь указан верно, то продолжаем
Process, Exist, Foobar.exe ; проверить существование процесса
If ErrorLevel ; если Foobar уже запущен, то...
WinActivate, ahk_class {E7076D1C-A7BF-4f39-B771-BCBE88F2A2A8}
; если не запущен, то...
Run, %Foobar_Path% ; запустить
Return ; закончить обработку горячей клавиши
;-------------------------------------------------------------------------------
; ========== ЗАКРЫТЬ FOOBAR ==========
;-------------------------------------------------------------------------------
NumpadIns & NumpadDel:: ; закрыть Foobar
Numpad0 & NumpadDot:: ; закрыть Foobar
;-------------------------------------------------------------------------------
FooBarControl( "exit" ) ; закрыть Foobar
Return ; закончить обработку горячей клавиши
;-------------------------------------------------------------------------------
; ========== СВЕРНУТЬ/РАЗВЕРНУТЬ ==========
;-------------------------------------------------------------------------------
NumpadIns & NumpadMult:: ; свернуть/развернуть
Numpad0 & NumpadMult:: ; свернуть/развернуть
;-------------------------------------------------------------------------------
WinGet, State, MinMax, ahk_class {E7076D1C-A7BF-4f39-B771-BCBE88F2A2A8}
If State = -1 ; если окно минимизировано, то...
FooBarControl( "show" ) ; восстановить свернутое окно
Else ; если окно НЕ минимизировано, то...
{
IfWinActive, ahk_class {E7076D1C-A7BF-4f39-B771-BCBE88F2A2A8}
FooBarControl( "hide" ) ; свернуть окно
Else ; если окно НЕ активно, то...
FooBarControl( "show" ) ; окно - на передний план
}
Return ; закончить обработку горячей клавиши
;-------------------------------------------------------------------------------
; ========== ВОСПРОИЗВЕДЕНИЕ/ПАУЗА ==========
;-------------------------------------------------------------------------------
NumpadIns & NumpadClear:: ; воспроизведение/пауза
Numpad0 & Numpad5:: ; воспроизведение/пауза
Media_Play_Pause:: ; обработка мультимедийной клавы
;-------------------------------------------------------------------------------
FooBarControl( "playpause" )
Return ; закончить обработку горячей клавиши
;-------------------------------------------------------------------------------
; ========== ПРЕДЫДУЩИЙ ТРЕК ==========
;-------------------------------------------------------------------------------
NumpadIns & NumpadLeft:: ; предыдущий трек
Numpad0 & Numpad4:: ; предыдущий трек
Media_Prev:: ; обработка мультимедийной клавы
;-------------------------------------------------------------------------------
FooBarControl( "prev" ) ; предыдущий трек
Return ; закончить обработку горячей клавиши
;-------------------------------------------------------------------------------
; ========== СЛЕДУЮЩИЙ ТРЕК ==========
;-------------------------------------------------------------------------------
NumpadIns & NumpadRight:: ; следующий трек
Numpad0 & Numpad6:: ; следующий трек
Media_Next:: ; обработка мультимедийной клавы
;-------------------------------------------------------------------------------
FooBarControl( "next" ) ; следующий трек
Return ; закончить обработку горячей клавиши
;-------------------------------------------------------------------------------
; ========== НАЗАД НА 5 СЕКУНД ==========
;-------------------------------------------------------------------------------
NumpadIns & NumpadHome:: ; назад на 5 секунд
Numpad0 & Numpad7:: ; назад на 5 секунд
^Media_Prev:: ; обработка мультимедийной клавы (CTRL+)
;-------------------------------------------------------------------------------
FooBarControl( "command:Seek back by 5 seconds" ) ; назад на 5 секунд
Return ; закончить обработку горячей клавиши
;-------------------------------------------------------------------------------
; ========== ВПЕРЕД НА 5 СЕКУНД ==========
;-------------------------------------------------------------------------------
NumpadIns & NumpadPgUp:: ; вперед на 5 секунд
Numpad0 & Numpad9:: ; вперед на 5 секунд
^Media_Next:: ; обработка мультимедийной клавы (CTRL+)
;-------------------------------------------------------------------------------
FooBarControl( "command:Seek ahead by 5 seconds" ) ; вперед на 5 секунд
Return ; закончить обработку горячей клавиши
;-------------------------------------------------------------------------------
; ============== ОСТАНОВИТЬ ===============
;-------------------------------------------------------------------------------
NumpadIns & NumpadEnd:: ; остановить
Numpad0 & Numpad1:: ; остановить
Media_Stop:: ; обработка мультимедийной клавы
;-------------------------------------------------------------------------------
FooBarControl( "stop" ) ; остановить воспроизведение
Return ; закончить обработку горячей клавиши
;-------------------------------------------------------------------------------
; ========== ВОСПРОИЗВОДИТЬ ВРАЗБРОС =============
;-------------------------------------------------------------------------------
NumLock & NumpadMult:: ; воспроизводить вразброс
;-------------------------------------------------------------------------------
FooBarControl( "command:Shuffle (tracks)" ) ; воспроизводить вразброс
Return ; закончить обработку горячей клавиши
;-------------------------------------------------------------------------------
; ========== ДИАЛОГ ОТКРЫТИЯ ФАЙЛОВ ==========
;-------------------------------------------------------------------------------
NumpadIns & NumpadDiv:: ; диалог открытия файлов
Numpad0 & NumpadDiv:: ; диалог открытия файлов
;-------------------------------------------------------------------------------
FooBarControl( "show" ) ; активизировать окно
FooBarControl( "command:Open..." ) ; вызвать окно открытия файлов
;~ FooBarControl( "command:Load PlayList..." ) ; окно открытия плейлистов
Return ; закончить обработку горячей клавиши
;-------------------------------------------------------------------------------
; ========== ОКНО - ПОВЕРХ ВСЕХ ==========
;-------------------------------------------------------------------------------
NumpadIns & NumpadUp:: ; окно Foobar - поверх всех
Numpad0 & Numpad8:: ; окно Foobar - поверх всех
;-------------------------------------------------------------------------------
FooBarControl( "command:Always on Top" ) ; окно - поверх всех
Return ; закончить обработку горячей клавиши
;-------------------------------------------------------------------------------
; ========== УМЕНЬШИТЬ ГРОМКОСТЬ =============
;-------------------------------------------------------------------------------
NumpadIns & NumpadSub:: ; уменьшить громкость
Numpad0 & NumpadSub:: ; уменьшить громкость
;-------------------------------------------------------------------------------
FooBarControl( "command:volume down" )
Return ; закончить обработку горячей клавиши
;-------------------------------------------------------------------------------
; ========== УВЕЛИЧИТЬ ГРОМКОСТЬ =============
;-------------------------------------------------------------------------------
NumpadIns & NumpadAdd:: ; увеличить громкость
Numpad0 & NumpadAdd:: ; увеличить громкость
;-------------------------------------------------------------------------------
FooBarControl( "command:volume up" )
Return ; закончить обработку горячей клавиши
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
FooBarControl( fooCommand ) ; функция управления foobar'ом
{
; В качестве параметра функция принимает параметр ком. строки для foobar'а (без слеша)
BatchLines_Before := A_BatchLines ; запоминаем текущие настройки скорости выполнения скрипта
SetBatchLines, -1 ; указываем максимальную скорость для скрипта
Process, Exist, foobar2000.exe ; проверяем существование процесса foobar2000
Foo_PID := ErrorLevel ; вносим PID в переменную
If NOT Foo_PID ; если процесс не существует, то...
Return ; выйти из функции
; если процесс существует, то продолжаем...
h_process := DllCall( "OpenProcess" ; открываем хендл процесса (права будут нужны для GetModuleFileNameExA)
, "UInt", 0x10|0x400 ; с нужными правами: 0x10 = PROCESS_VM_READ, 0x400 = PROCESS_QUERY_INFORMATION
, "Int" , False ; без наследования хендла
, "UInt", Foo_PID ) ; для указанного PID'а
If ( ErrorLevel OR h_process = 0 ) ; если почему-либо не удалось открыть хендл (или он открыт для несуществующего PID'а)...
Goto, fbc_Return ; перейти к закрытию хендла и выйти из функции
VarSetCapacity( FooExePath, 255 ) ; обеспечиваем достаточную вместимость переменной (путь в символах, длиннее не бывает)
DllCall( "psapi.dll\GetModuleFileNameExA" ; получаем путь к исполнимому файлу процесса GetModuleFileNameExA-(ANSI)
, "UInt", h_process ; для указанного хендла процесса
, "UInt", 0 ; нас интересует не модуль, а целиком процесс
, "Str" , FooExePath ; переменная, получающая путь
, "UInt", 255 ) ; 255 - длина извлекаемого пути в символах (длиннее не бывает)
fbc_Return: ; метка перехода к закрытию хендла процесса
DllCall( "CloseHandle", "UInt", h_process ) ; закрываем хендл процесса
RunWait, %FooExePath% /"%fooCommand%" ; отправить команду foobar'у (и дождаться её выполнения)
SetBatchLines, %BatchLines_Before% ; восстанавливаем скорость скрипта
Return ; выйти из функции
} ; конец функции
;-------------------------------------------------------------------------------
Путь к Foobar'у в этом скрипте всё-таки указан, но он используется только для запуска плеера. Для всех остальных команд управления - он не нужен. Т.е. этот путь можно не указывать.
А здесь можно посмотреть и взять скрипт, совмещающий управление Foobar'ом и WinAmp'ом