Дистанционное управление презентацией со смартфона

в 4:21, , рубрики: python, Презентации

Делал я недавно доклад (на Percona Live). И как-то ночью (jet-lag все-таки) подумал, что неплохо бы как-нибудь видеть свои комментарии к слайдам — подсказки — и переключать слайды не подходя к ноутбуку. Чудо-устройства, чтоб и слайды переключало и комментарии показывало, у меня не было. Но был смартфон с Андроидом. Гугл-маркет разочаровал. Большинство подобных приложений работало только с PowerPoint, для LibreOffice я нашел только одно, платное, и выглядело оно как-то не так.

Но есть простое решение — браузер. Можно поднять http-сервер на ноутбуке, зайти с телефона, и по ссылкам переключать слайды. И будет работать не только с Андроидом, а и с яблочными, и с виндофонами. Да вообще смартфон не нужен, можно хоть через WAP заходить, или с другого ноутбука.

Получилось довольно просто. Около 70 строк на питоне, никаких внешних зависимостей (почти).

Комментарии читаются из файла (заморачиваться с вытаскиванием их из презентации я не стал). Поднимаем BaseHTTPServer на каком-то порту, я пробую все от 8000 до 9000 в случайном порядке, пока не получится. По инструкции со StackOverflow определяем свой IP. И вдобавок генерируем большое случайное число — оно будет частью URL-а, чтобы никто из аудитории не переключал нам слайды. Как мелкое удобство открываю браузер, чтобы показал QR-код для доступа к серверу. Если доступа в Интернет во время конференции не будет — не беда, придется ввести URL руками, и все. А для работы достаточно внутреннего вайфая.

По инструкции к BaseHTTPServer, чтобы обрабатывать GET запросы надо создать do_GET метод. Создаем. Первым делом надо проверить, чтоб было наше случайное число. Если есть, и URL заканчивается на next или prev, то имитируем нажатие пробела или, соответственно, backspace, и возвращаем страничку с комментариями для следующей или предыдущей страницы.

У меня стоит fvwm, так что с имитацией нажатий проблем не возникло. Для других менеджеров окон можно использовать отдельную программку или даже специальный модуль для питона, такие есть — я проверял.

Ну, собственно, и все. Только шрифт в настройках мобильного браузера нужно делать покрупнее. И комментарии писать покороче, иначе их долго читать — получаются неприятные паузы во время доклада. Да, и таймаут на отключение экрана убрать на смартфоне и в ноутбуке.

Испытание в боевых условиях прошло успешно.

#!/usr/bin/python

import sys
import os
import random
import socket
import BaseHTTPServer
import re

handler_class=BaseHTTPServer.BaseHTTPRequestHandler
token="/" + str(random.randint(0, sys.maxint)) + "/"
page = 1
validate = re.compile(token + "(prev|next)$")

def send_key(key):
  os.system("FvwmCommand 'All (VCLSalFrame) FakeKeypress press {}'".format(key))

class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
  def link(self,s,n):
    if n < 0 or n >= len(data):
      return " "
    return '<a href="{}{}">{}</a>'.format(token,s,s)

  def do_GET(self):
    cmd = validate.match(self.path)
    if cmd is None:
      self.send_response(404)
      self.send_header("Content-type", 'text/html')
      self.end_headers()
      self.wfile.write('<h1>OK</h1>')
      return

    global page
    if cmd.group(1) == 'prev' and page > 0:
      page = page - 1
      send_key('BackSpace')
    elif cmd.group(1) == 'next' and page < len(data)-1:
      page = page + 1
      send_key('space')
     
    self.send_response(200)
    self.send_header("Content-type", 'text/html; charset=utf-8')
    self.end_headers()
    self.wfile.write("""
{pagenum} - {next}
<hr> {data} <hr>
{prev} - {pagenum}
""".format(prev = self.link('prev', page - 1), pagenum = page + 1,
           next = self.link('next', page + 1), data = data[page]))

def read_file(s):
  with open(s) as f:
    return re.split('--- *n?', f.read())

def ip():
  s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  s.connect(('192.168.1.1', 0)) # fake, but nobody cares
  return s.getsockname()[0]

def make_url(port):
  url="http://{}:{}{}prev".format(ip(), port, token)
  print url
  os.system("firefox 'http://chart.apis.google.com/chart?cht=qr&chs=200x200&chl={}' &".format(url))

def run():
  for port in random.sample(xrange(8000, 9000),1000):
    try:
      httpd = BaseHTTPServer.HTTPServer(('',port), Handler)
      httpd.server_activate()
      make_url(port)
      httpd.serve_forever()
    except socket.error, e:
      if e.errno not in (98,):
        print e
        exit()
    except KeyboardInterrupt:
      print "nExiting"
      exit()

data = read_file('notes.txt')
print "Got {} slides".format(len(data))
run()

Автор: petropavel

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js