1 (изменено: Androgen, 2007-05-05 18:10:57)

Тема: 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'ом

Post's attachments

FooBarControl.zip 2.76 kb, 701 downloads since 2007-05-05 

You don't have the permssions to download the attachments of this post.
Крокодил, крокожу и буду крокодить! (Твёрдое обещание нетрезвого кодера).