Добрый день друзья, хочу сразу высказаться: данная статья моего друга, который хотел её опубликовать, но по ошибке отправил в песочницу не доделанную, и более не смог выложить нормальный вариант, попросил об этом сделать меня. Лично для меня статья очень полезная, так что весь этот труд исключительно blide!
Играя в Team Fortess 2 и при этом слушая музыку, я сильно негодовал из-за невозможностью регулировки громкости проигрывателя Clementine отдельно от общей громкости. Но лишних клавиш на клавиатуре у меня нет, все используются.
Нетривиальная задача должна иметь нетривиальное решение, поэтому я решил сделать эмуляцию нажатия клавиш через мое android-устройство посредствам http. Незнание Java и Python ничем не помешало, не спроста же у меня на жёстком диске есть ext3-раздел.
Для начала требовалось узнать список поддерживаемых и свободных клавиш. В Ubuntu можно с помощью утилиты xmodmap и файликов /usr/library/X11/*keysum.h Для меня таковыми оказались:
#define XF86XK_Launch0 0x1008FF40 /* Launch Application */ … #define XF86XK_LaunchF 0x1008FF4F /* Launch Application */
Нам нужны коды данных клавиш(я выбрал только 2); например, узнать код клавиши с обозначением «XF86XK_Launch1» можно с помощью команды «xmodmap -pk|preg ‘Launch1’
», мы получим код «156»(мной выбраны 156 и 157).
Сервер
Пользуясь наижелезнейшей логикой, я понял, что tcp-сервер я буду писать на незнакомом мне Python 3 с помощью модуля http. Этот этап не вызвал никаких трудностей, потому что в модуле есть достаточно хорошая и понятная основа для написания tcp-сервера, а именно классы «BaseHTTPRequestHandler» и «SimpleHTTPRequestHandler». Для эмуляции нажатия клавиш был использован «pyatspi.registry», ну тут собственно нечего комментировать.
В процессе дебагинга мне показалось, что весьма полезным будет знать время отклика, но тут случилось что-то интересное; в эмуляторе данная фича работала как надо, а вот время отклика, полученное при работе с физическим девайсом, заставило меня переосмыслить идеи об устройстве мира. Постепенно мне начало казаться, что я — гуру программирования и магистр времени. Иначе как мне удалось бы сократить время отклика до отрицательных значений? Я готов выслушать ваши теорию по данному прецеденту.
import pyatspi, time import http.server import socketserver class HttpKeyboard(http.server.BaseHTTPRequestHandler): server_version = "SimpleHTTP/0.1" def do_GET(self): """Serve a GET request.""" reg = pyatspi.Registry.generateKeyboardEvent path = self.path.split('/') if len(path) == 3: ms = int(round(time.time() * 1000)) - int(path[2]) reg(int(path[1]), None, pyatspi.KEY_PRESSRELEASE) print ("key %s - %s ms" % (path[1], ms)) f = self.send_head() def send_head(self): self.send_response(200) self.send_header("Content-type", "text/html; charset=utf-8") self.send_header("Content-Length", 0) self.end_headers() httpd = socketserver.TCPServer(("", 8000), HttpKeyboard) print("serving at port", 8000) if __name__ == "__main__": httpd.serve_forever()
В этой библиотеке есть пример обработчика запросов — класс SimpleHTTPRequestHandler, который может хорошо помочь при работе с ней.
Кстати, если запустить скрипт в консоли, то после обработки запросов он будет выводить:
key 156 - 527 ms // код клавиши и задержка(которая бывает меньше нуля)
192.168.0.101 - - [07/Jan/2013 19:57:09] "GET /156/1357574229198 HTTP/1.1" 200
В данном случае:
156 — код клавиши
1357574229198 — время нажатия кнопки на вдвойнедополнительной клавиатуре
Добавить http-заголовки я решил, чтобы результат запроса можно было бы обработать на девайсе готовыми средствами.
Android-приложение
Для асинхронных запросов я выбрал Android Asynchronous Http Client. Устройства находятся в одной wifi-сетке, поэтому использовались внутренние ip, больше ничего интересного на данном этапе я не нашёл кроме враждебно настроенной System.currentTimeMillis(). Полные сорцы скину в конце, а тут оставлю функцию самого запроса.
public void KeyHttp(String key) { AsyncHttpClient client = new AsyncHttpClient(); EditText edit = (EditText) findViewById(R.id.editText1); client.get("http://"+edit.getText()+"/"+key+"/"+System.currentTimeMillis(), new AsyncHttpResponseHandler() { @Override public void onSuccess(String response) { this.log("success result"); } @Override public void onStart() { this.log("starting"); } @Override public void onFailure(Throwable error) { this.log("failure result"); } public void log(String text) { TextView view = (TextView) findViewById(R.id.textView1); view.setText(text); } }); }
Итог
Запустим сервер и установим приложение на девайс.
Ну вот, теперь всё готово для комфортного увеличения игрового времени на linux-машине в Team Fortress 2 под бунтарские ритмы The Offspring.
Клавиши можно использовать любые и в любом количестве. Я частенько вижу у знакомых телевизор и пк подключенные через hdmi, но находящиеся в разных комнатах, такой itlife-хак, думаю, пришёлся бы им по душе. На самом деле сфера применения данного инструмента достаточно широка: от домашних медиа-центров до недомашних медиа-центров.
Спасибо за интерес к материалу.
Ссылки:
Android Asynchronous Http Client (http://loopj.com/android-async-http/)
http.server (http://docs.python.org/3.2/library/http.server.html)
Пишем своё первое приложение на Android (http://habrahabr.ru/post/109944/)
man xmodmap
*синюю изоленту не использовал специально, хотелось бы попользоваться телефоном отдельно от клавиатуры
ссылка на оригинал статьи http://habrahabr.ru/post/165639/
Добавить комментарий