Управление плеером vk.com
с клавиатуры
Для Chrome/Chromium
Хороший программист печатает порядка 50 слов в минуту или около 5 символов в секунду. Таким образом, отвлечение от программирования (или других полезных занятий, вроде чтения Хабра) на переключение музыки в плеере — непозволительная роскошь.
И если любой уважающий себя плеер имеет возможность установки горячих клавиш (например, Audacious), то музыкальный плеер vk.com ввиду ограничений Веба, а скорее и просто уже исходя из KISS — нет.
Наш ответ маусфагам
На текущий момент — 2014-01-10 02:15 — для Chrome существует удобный и простой фреймворк из js (и Dart) API для написания расширений и даже приложений. Впрочем, набор достаточно ограниченный и со своими особенносятми. Так, например, хотя мы и можем внедрять скрипты в загружаемые страницы, что необходимо для взаимодействия с сайтами, однако непосредственно вызывать их функции — нет. Конечно, это сделано по причинам безопасности и даже упрощает разработку, так как в sandbox'е не нужно заботиться о конфликтах. Однако, такой простой и нужной вещи, как глобальные горячие клавиши в API нет.
Поэтому, хотя мы и можем перехватывать нажатия клавиш на страницах, но это работает только при открытом браузере, что явлется решением проблемы лишь наполовину. Но Chrome API для приложений предоставляет socket-интерфейсы, т.е. наше приложение для Chrome может открывать socket-соединения и даже поднимать udp или tcp-серверы. Чем мы и воспользуемся.
Итак, мы разделим нашу утилиту на две части:
- расширение, внедряющее в интересующие нас страницы код, управляющий плеером vk.com посредсвом старого-доброго DOM;
- приложение, поднимающее слушающий tcp-сервер и передающее команды в расширения.
Данное разделение необходимо, так как Chrome API не предоставляет своё socket-подмножество для расширений, но только для приложений. В дальнейшем достаточно с помощью наших самых любимых средств повесить хоткеи на запросы к этому серверу и вуаля. Хоткеи.
Из жизни расширений
Управление плеером в совсем немного упрощённом виде происходит так:
function vk_click(btn) {
if (document.getElementById('ac_'+btn)) {
document.getElementById('ac_'+btn).click();
} else if (document.getElementById('pd_'+btn)) {
document.getElementById('pd_'+btn).click();
} else {
document.getElementById('head_music').click();
sleep(...)
document.getElementById('pd_'+btn).click();
document.getElementById('head_music').click();
}
}
где btn
— одна из кнопок плеера: "play", "next" и т.д.
Остальной код, включая tcp-сервер, основывается на приерах Google отсюда. Единственно, что хочу заметить, пример с tcp-сервером вёл себя немного странно, пока я не выпилил весь код по учёту и ограничению числа подключений.
Расширение описывается таким json-манифестом:
{
"manifest_version": 2,
"name": "vkmb ext 0.1",
"description": "nothing",
"version": "0.1",
"content_scripts": [
{
"matches": ["http://vk.com/*", "https://vk.com/*"],
"css": ["main.css"],
"js": ["injection.js"]
}
],
"permissions": [
"tabs", "http://*/", "https://*/*", "notifications"
],
"browser_action": {
"default_icon": "./icons/pause48.png",
"default_popup": "popup.html"
},
"background": {
"scripts": ["background.js"]
}
}
где самая интересная скобка — это
"content_scripts": [
{
"matches": ["http://vk.com/*", "https://vk.com/*"],
"css": ["main.css"],
"js": ["injection.js"]
}
]
описывающая куда и что внедрять. В данном случае мы внедряем наш файл injection.js
во все страницы социальной сети.
Контент-скрипты расширения умеют принимать сообщения от других расширений или приложений Chrome, чего вполне достаточно для организации сообщения между Chrome-приложением и контент-инъекциями.
Исходные коды расширения и приложения. Предупрежедение: код довольно сырой и содержит целые никем не используемые сейчас фрагменты.
Добавление в Chrome
- Первое, на всякий случай включите флажок Experimental Extension APIs по адресу chrome://flags. (Мне кажется, они не используются, но just in case).
- Теперь необходимо установить расширение в режиме девелопера и
- прописать id расширения в файл
vkmbapp/commands/BrowserCommands.js
var extid = 'jfnojchndfhpbfbfbopjgnggifooobpj'; <-----------
- Установить приложение vkmb app и Launch-нуть его.
В системе должен будет зарегестрироваться новый tcp-сервер на 2812:
ors@orsbook:~$ netstat -Ainet -ln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:2812 0.0.0.0:* LISTEN
Горячее
Сами хоткеи. Вообще, с нашим сервером можно пообщаться и лично, например, с помощью nc:
ors@orsbook:~$ nc 127.0.0.1 2812
hi
hi
Unknown command hi. Try "help"
help
echo Echo the arguments
open Open the given URL
vknextsong vk.com Music Playback - Next song
vkprevsong vk.com Music Playback - Pervious song
vkplay vk.com Music Playback - Play
vkpause vk.com Music Playback - Play
vkaddsong vk.com Music Playback - Add to my music
bye Close connection
vknextsong
ok
bye
Завершать диалог рекомендую не по Ctrl+C
, а специальной командой bye
— будьте вежливы! Хоткеи соответсвенно можно вещать на нечто подобное
$ printf "vknextsong\r\nbye\r\n" |
ncat -d 100ms 127.0.0.1 2812
(Тут искушённый читатель заметит 100 миллисекундную задержку. Да, она, действительно, по каким-то неведомым мне причинам необходима для того, чтобы приложение Chrome правильно принимало tcp-команды.)
Для openbox'а, к примеру, достаточно добавить в rc.xml
<keybind key="W-Left"><action name="Execute"><command>
/bin/sh -c 'printf "vkprevsong\r\nbye\r\n" |
ncat -d 100ms 127.0.0.1 2812'
</command></action></keybind>
<keybind key="W-Right"><action name="Execute"><command>
/bin/sh -c 'printf "vknextsong\r\nbye\r\n" |
ncat -d 100ms 127.0.0.1 2812'
</command></action></keybind>
<keybind key="W-Up"><action name="Execute"><command>
/bin/sh -c 'printf "vkplay\r\nbye\r\n" |
ncat -d 100ms 127.0.0.1 2812'
</command></action></keybind>
<keybind key="W-Down"><action name="Execute"><command>
/bin/sh -c 'printf "vkpause\r\nbye\r\n" |
ncat -d 100ms 127.0.0.1 2812'
</command></action></keybind>
<keybind key="W-KP_Add"><action name="Execute"><command>
/bin/sh -c 'printf "vkaddsong\r\nbye\r\n" |
ncat -d 100ms 127.0.0.1 2812'
</command></action></keybind>
В других OS и WM это так же всегда можно сделать. Для полной автоматизации не хватает только автоматического запуска нашего приложения Chrome, поэтому стоит добавить команду вида google-chrome --app-id=ifbelmdaiiikjchdololofceagckhoof
в автозапуск.
Заключение
Хотя такое решение и является переусложнённым, тем не менее, socket-интерфейс позволяет при желании прикруить LRC, custom front-end или управление по сети!
Данная тулза написана совсестно с dortonway. Пишите нам на dortonway@gmail.com или shitpoet@gmail.com.
Берегите своё время. Всем счастливого mouseless экспириенса]
shitpoet@gmail.com