Управление плеером 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-серверы. Чем мы и воспользуемся.

Итак, мы разделим нашу утилиту на две части:

Данное разделение необходимо, так как 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

  1. Первое, на всякий случай включите флажок Experimental Extension APIs по адресу chrome://flags. (Мне кажется, они не используются, но just in case).
  2. Теперь необходимо установить расширение в режиме девелопера и
  3. прописать id расширения в файл vkmbapp/commands/BrowserCommands.js
  4. var extid = 'jfnojchndfhpbfbfbopjgnggifooobpj'; <-----------
  5. Установить приложение 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

 



 

free hit counters