AI Как я настраивал глобальные горячие клавиши для Яндекс Музыки (что делать с RDP), и почему в итоге пришёл к джойстику

AI

Редактор
Регистрация
23 Август 2023
Сообщения
3 600
Лучшие ответы
0
Реакции
0
Баллы
243
Offline
#1
История простая: после очередного обновления Windows 10 у меня начали странно работать мультимедийные клавиши. Привязка к текущему приложению иногда теряется и работать вообще перестает. Плюс ещё бесило стандартное всплывающее окно управления музыкой — оно висит вечность и закрыть его нельзя.



В какой‑то момент я понял, что терпеть это уже не хочется, и пошёл разбираться, как всё починить.

Почему всё сломалось


После обновления Windows система начала периодически терять активное медиа‑приложение. Проще говоря — Windows иногда просто не понимает, какое приложение сейчас должно получать команды «пауза», «следующий трек» и т.д.

Первая попытка — PowerToys


Сначала я попробовал пойти по простому пути и использовать Microsoft PowerToys — переназначал горячие клавиши, экспериментировал с биндингами. Но быстро стало понятно, что это не решает корневую проблему. Если Windows теряет активное медиа‑приложение, то никакие красивые биндинги не спасают.

Поэтому пришлось идти дальше и брать более гибкий инструмент — AutoHotkey.

Эксперименты с AutoHotkey

Попытка №1 — просто отправлять медиа‑кнопки


Самый очевидный вариант — просто пересылать мультимедийные команды:

Media_Play_Pause::Send, {Media_Play_Pause}
Media_Next::Send, {Media_Next}
Media_Prev::Send, {Media_Prev}

Но из‑за той же самой проблемы с «потерей активного плеера» это работало нестабильно: иногда команда проходила, иногда — нет.

Попытка №2 — побороть зависающее системное окно


Меня ещё раздражало, что при переключении трека появляется системное окно (Media OSD), которое долго висит на экране. Я попробовал хитрость — дополнительно дергать громкость, чтобы окно быстрее закрывалось:

Media_Next::
Send {Volume_Up}
Send {Volume_Down}
return

Работает… но костыльно. Понятно что фокус всё теряется.

Попытка №3 — свои комбинации клавиш


Дальше я решил повесить управление музыкой на собственные сочетания, например Ctrl + Alt + стрелки:

^!Right::
ControlSend,, {Media_Next}
return

^!Left::
ControlSend,, {Media_Prev}
return


Стало удобнее переключаться, но двигаемся дальше.

Попытка №4 — жёстко управлять фокусом окна


В какой‑то момент стало понятно: надо не надеяться на Windows, а самому управлять окном Яндекс Музыки.

Логика такая:


  1. Найти окно Яндекс Музыки.


  2. Активировать его.


  3. Отправить нужную клавишу (в настройках приложения можно найти список горячих клавиш).


  4. Свернуть обратно.

Финальный вариант выглядел примерно так:

PlayPause:
if WinExist("ahk_exe Яндекс Музыка.exe")
{
WinActivate
Sleep, 200
Send, k ; Play/Pause в Яндекс Музыке
WinMinimize
}
return

Да, окно на долю секунды мелькает, но зато команды работают стабильно и больше не появляется раздражающее системное окно.

Неожиданная проблема — раскладка клавиатуры


Когда всё вроде бы заработало, всплыла новая проблема: при русской раскладке буквы (k, n, p) отправлялись неправильно.

Решение простое — отправлять не буквы, а скан‑коды клавиш:

Send, {sc019} ; вместо буквы P

После этого раскладка вообще перестала иметь значение.

А что насчёт RDP?


Естественно, мне захотелось, чтобы всё это работало и когда я нахожусь в RDP. Тут я потратил кучу времени: пробовал разные программы, советы ИИ, хаки — но почти всё упиралось в ограничения самого RDP. Он очень агрессивно перехватывает ввод.

В итоге стало понятно: чисто программно эту задачу нормально не решить.

Поспрашивал ИИ, сначала он мне предложили купить отдельный USB‑нумпад. Но почти все такие устройства — это просто цифры от 0 до 9. Для управления музыкой это неудобно.

И тут я вспомнил, что у меня валяется джойстик от PS5. Подключил его — Windows увидела его сразу, AutoHotkey тоже без проблем начал ловить кнопки.

Клавиши ловил через вот этот небольшой скрипт:

#NoEnv
#SingleInstance Force

; Тест всех кнопок геймпада
SetTimer, ShowJoystick, 100
return

ShowJoystick:
; Проверяем все кнопки
buttons := ""
Loop, 32
{
if GetKeyState("Joy" . A_Index)
buttons .= A_Index . " "
}

; Проверяем D-Pad (POV)
pov := GetKeyState("JoyPOV")

; Проверяем стики
x := GetKeyState("JoyX")
y := GetKeyState("JoyY")
z := GetKeyState("JoyZ")
r := GetKeyState("JoyR")

; Показываем всё
ToolTip, Button: %buttons%`nPOV (D-Pad): %pov%`nleft stick X/Y: %x% / %y%`nrighr stick Z/R: %z% / %r%, 0, 0
return

Esc::ExitApp ; Закрыть по Esc

Назначил кнопки:

Joy1::Gosub, PrevTrack ; предыдущий трек
Joy3::Gosub, NextTrack ; следующий трек
Joy14::Gosub, PlayPause ; пауза / воспроизведение
Joy13::Gosub, ActivateMusic ; активировать яндекс музыку, если нет окна, то запустить

И внезапно это оказалось максимально удобным решением. Работает стабильно, в том числе и если находимся в RDP.

Управление громкостью и дополнительные бонусы


На свободные кнопки я повесил громкость:

Joy4:: Send {Volume_Up}
Joy2:: Send {Volume_Down}

Но в RDP такие команды улетают в удалённую машину. Поэтому я переделал это на прямое управление системной громкостью:

Joy4:: SoundSet +1
Joy2:: SoundSet -1

А потом сделал приятный бонус — чтобы при удержании кнопки громкость плавно менялась:

Joy4::
while GetKeyState("Joy4", "P")
{
SoundSet +1
Sleep 50
}
return
Добавил установку лайков и дизлайков


Подумал и на клавиши вверх и вниз добавил лайки и дизлайки. Тут все немного посложнее, но ИИ как обычно справился.

CheckPOV:
POV := GetKeyState("JoyPOV")

if (POV = 0 && !POVPressed) ; Вверх - лайк
{
POVPressed := true
Gosub, LikeTrack
}
else if (POV = 18000 && !POVPressed) ; Вниз - дизлайк
{
POVPressed := true
Gosub, DislikeTrack
}
else if (POV = -1) ; Отпущен
POVPressed := false
return
Что получилось в итоге


В результате у меня получилось:


  • стабильное управление музыкой;


  • не зависит от раскладки клавиатуры;


  • работает даже когда находимся в окне RDP;


  • нет раздражающего системного окна;


  • удобное управление с отдельного устройства;


  • установка лайков и дизлайков;


  • плавная регулировка громкости.

Бонусом оказалось то, что джойстики стоят недорого, легко подключаются к Windows и имеют много удобных кнопок разной формы — их легко запомнить на ощупь. В этом плане они даже удобнее нумпадов и клавиатур.

Если у вас потребность в дополнительных клавишах для любой вашей программы, можете также купить джойстик и модифицировать мой скрипт 🙂

Итоговый скрипт


Запускать его надо на AHK 1.1, скачать можно тут: https://www.autohotkey.com/

#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%
#SingleInstance Force

if not A_IsAdmin ; К сожалению зачем то нужны права админа, без них Яндекс Музыка не вызывается
{
Run *RunAs "%A_ScriptFullPath%"
ExitApp
}

; === Проверка D-Pad ===
SetTimer, CheckPOV, 100 ; запускаем таймер
return

CheckPOV:
POV := GetKeyState("JoyPOV")

if (POV = 0 && !POVPressed) ; Вверх - лайк
{
POVPressed := true
Gosub, LikeTrack
}
else if (POV = 18000 && !POVPressed) ; Вниз - дизлайк
{
POVPressed := true
Gosub, DislikeTrack
}
else if (POV = -1) ; Отпущен
POVPressed := false
return

Media_Play_Pause::Gosub, PlayPause

; === Кнопки PS5 ===
Joy1::Gosub, PrevTrack ; Квадрат (□) - предыдущий
Joy3::Gosub, NextTrack ; Круг (○) - следующий
Joy14::Gosub, PlayPause ; Тачпад - воспроизведение\пауза
Joy13::Gosub, ActivateMusic ; PS - активировать яндекс музыку

; === Процедуры ===
Joy4:: ; Треугольник (△) - громче
while GetKeyState("Joy4", "P")
{
SoundSet +1
Sleep 50
}
return

Joy2:: ; Крест (✕) - тише
while GetKeyState("Joy2", "P")
{
SoundSet -1
Sleep 50
}
return

PlayPause:
if WinExist("ahk_exe Яндекс Музыка.exe")
{
WinActivate
Sleep, 200
Send, {sc025}; k
WinMinimize
}
return

NextTrack:
if WinExist("ahk_exe Яндекс Музыка.exe")
{
WinActivate
Sleep, 200
Send, {sc031}; n
WinMinimize
}
return

PrevTrack:
if WinExist("ahk_exe Яндекс Музыка.exe")
{
WinActivate
Sleep, 200
Send, {sc019}; p
WinMinimize
}
return

LikeTrack:
if WinExist("ahk_exe Яндекс Музыка.exe")
{
WinActivate
Sleep, 200
Send, {sc021}; f
WinMinimize
}
return

DislikeTrack:
if WinExist("ahk_exe Яндекс Музыка.exe")
{
WinActivate
Sleep, 200
Send, {sc020}; d
WinMinimize
}
return

ActivateMusic:
if WinExist("ahk_exe Яндекс Музыка.exe")
{
WinActivate
}
else
{
Run, %LOCALAPPDATA%\Programs\YandexMusic\Яндекс Музыка.exe
}
return
 
Яндекс.Метрика Рейтинг@Mail.ru
Сверху Снизу