Travel hacks

Решил добавить и свои пять копеек в тему про подготовку к самостоятельным путешествиям. Может мои хаки будут кому-то полезны.

Любое путешествие начинается с плана поездки, а каждый план нужно эффективно обсуждать со всеми участниками поездки. В качестве такого места я уже давно остановил свой выбор на Hackpad, в нем каждый из участников накидывает свои идеи, потом отбрасываем то, что выходит за рамки бюджета или не успеваем по времени и в конце концов сортируем по дням.

Когда план готов самое время сохранить его для поездки и таким местом у меня неизменно выступает OneNote, а поскольку он установлен на всех устройствах, то во время поездки я могу эффективно смотреть за тем куда мы хотели попасть и корректировать личные пометки.

OneNote

Кроме плана, я заношу в него общую информация о месте поездки:

  • Правила работы и оплаты общественного транспорта;
  • Хорошие рестораны, бары и магазины;
  • Краткое резюме после посещения достопримечательности;
  • Наличие беспроводного интернета;
  • Возможные скидки для туристов.

Самым логичным было бы хранить все билеты и ваучеры бронирования в нем, но в этом плане OneNote показывает себя как неповоротливая и тормозная штука. Все билеты я сохраняю в PDF и храню в iBooks и дублирую копии в Dropbox.

Дешевые авиабилеты и жилье я искал через собственную форму для поиска билетов. Когда все места и билеты собраны, самое время подумать о карте, и нет лучшей offline карты чем Maps.me. Все места из Hackpad я отмечаю на создаваемых картах Google. А когда карта и маршруты построены, то можно выгрузить все точки и маршруты единым файлом в формате KML на Dropbox.

Теперь имея готовый файл, открываю его в программе Maps.me на всех устройствах и готово - offline карта с отметками достопримечательностей и GPS навигацией. Можно не зависеть от интернета и в любом месте не бояться заблудиться.

Немного о сборах, перепробовав целую кучу разных решений я остановился на единственной программе которая не заставляла меня вписывать вес каждой вещи, делить вещи по чемоданам и заниматься чем-либо помимо хранения списков. Такой программой для меня стала Travel List.

Travel List

В заключение хотел бы рассказать фейле всех программ по работе с планом путешествия или помощью по ориентированию в аэропорту (да-да я про GateGuru). Подавляющее большинство из них предполагают, что на протяжении всего путешествия у вас будет беспроводной интернет, а поскольку это далеко не так, то даже самые популярные программы которые призваны сэкономить время путешественникам превращаются в бесполезные иконки на экране телефона.

Raspberry Pi - Finn

Продолжаю рассказывать о своем зоопарке одноплатных компьютеров Raspberry Pi. И если в прошлый раз я рассказывал ретро консоле, то в этот раз расскажу о другой малине, которая играет роль дополнительного медиа центра и прекрасно дополняет все недостатки присутствующие в моем Apple TV 2 с надстройкой aTV Flash.

Больше всего в Apple TV меня смущало отсутствие поддержки 1080p, а также не удобный YouTube клиент. А к мелким недостаткам я всегда относил наличие дополнительного пульта управления, который всегда теряется.

Сердце медиа центра — OpenELEC и нет смысла подробно останавливаться на процессе сборки и установки его на Raspberry Pi:

  • Для начала качаем готовый Diskimage с сайта OpenELEC;
  • Записываем образ на SD флешку;
  • Вставляем в Raspberry Pi флешку, HDMI кабель и питание;
  • Включаем ТВ и наслаждаемся.

Главное преимущество OpenELEC перед чистой установкой Kodi (бывшим XBMC) на Raspbian, это отсутствие проблем с настройкой , все делается максимально просто прямо с ТВ пульта. Никаких клавиатур и возни с терминалом не требуется.

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

Медиа библиотека лежит на NAS’е и доступна по локальной сети, так что оба медиа центра независимо друг от друга имеют к ней полный доступ.

Ну и в качестве заключения этой заметки скажу что порадовал все свои малины, подключив их питание через единый 5-портовый USB хаб от Anker.

Raspberry Pi

Оцифровка старых VHS кассет

Время идет и когда то привычные форматы хранения записей сейчас кажутся архаичными. Так и произошло когда собравшись выбросить свой старый VHS-магнитофон я обнаружил небольшой архив личных видео записей на VHS-C кассетах. Засунув их в видео камеру я с удивлением обнаружил, что видео камера за 10 лет простоя уже отказывается воспроизводить звук, а само качество видео становится все хуже.

Собравшись силами и терпением я решил оцифровать всю немногочисленную коллекцию VHS-C кассет. Чтобы все сделать в домашних условиях я воспользовался самым популярным решением, которое можно найти на прилавках китайских магазинов, а именно - EasyCap. А также адаптером c VHS-C на VHS кассеты.

EasyCap

Говоря о EasyCap, главное на что стоит обратить внимание при его выборе и покупке - это чип, на основе которого он сделан, мой оказался на китайском чипе Fushicai usbtv007 (EasyCap DC60++), что неприятно отразилось невозможностью использования программы захвата EasyCapViewer под OSX. Уже после покупки прочитав про разнообразие начинки данного класса устройств, самым оптимальным вариантом для покупки стало бы что-то на чипе Syntek или Somagic. В устройствах на этих чипах используется отдельный процессор для обработки звука, в отличии от usbtv007.

Захват с VHS

В случае с usbtv007 пришлось прибегнуть к компьютеру с Windows. Для захвата видео я использовал VirtualDub и кодек huffyuv. Про установку huffyuv под Windows 8 скажу сразу, что испробовал массу методов, а единственным удачным решением стал запуск командной строки от администратора и установив кодек используя команду:

%WINDIR%\syswow64\rundll32.exe setupapi.dll,InstallHinfSection DefaultInstall 0 c:\<путь_к_кодеку>\huffyuv.inf​

Для оцифровки я использовал один из многочисленных мануалов по захвату видео, а потому просто перечислю список плагинов VirtualDub которые были наложены на видео, для того чтобы VHS картина выглядела прилично:

Потратив не мало вечеров на захват видео в котором бы не было рассинхронизации видео и звука, на выходе у меня получился набор файлов размером от 10 до 20 GB каждый, в зависимости от времени кассеты.

Сжатие x264

Имея на каждую видеокассету по видеофайлу я воспользовался инструкцией по обработке и пересжатию видео. Используя программу MeGUI и кодек x264, после сжатия получились файлы приемлемых 700мб, на каждую кассету при разрешении 640х480.

Теперь имя полный набор оцифрованные копии всех VHS кассет можно спокойной совестью выбрасывать, занимающий место, видео магнитофон и камеру.

Raspberry Pi - BMO

Уже около года я являюсь счастливым обладателем нескольких Raspberry Pi, а написать о том как я их использую в домашней обстановке все руки не доходили. Решил восполнить этот пробел и писать по одной заметке на каждую малину из тех, что есть у меня.

Когда я приобрел свой первый Raspberry Pi, то первая мысль которая закралась у меня в голове, а почему бы не использовать ее в качестве игровой консоли для ретро игр. Собрав в голове некий план необходимых покупок и узнав о возможностях запуска эмуляторов на Raspberry Pi, я составил небольшой список необходимых компонентов.

Raspberry Pi

Для своей будущей консоли я использовал:

  • Raspberry Pi Model B с корпусом Pibow
  • WiFi свисток Edimax EW-7811UN
  • Джойстик Classic USB Super Nintendo Controller for PC
  • SanDisk Ultra 8GB SDHC Class 10
  • Кабель AmazonBasics High-Speed HDMI Cable
  • Кабель miniUsb-USB
  • А также зарядник USB на 2А

Не вдаваясь в подробности первичной настройки упомяну лишь, что для своей игровой консоли я использовал классический дистрибутив Raspbian, и назвал ее сетевым именем BMO-Pi. Каждый из своих Raspberry Pi я называю героями из сериала Adventure Time.

Поискав подходящие платформы для эмуляции, я наткнулся на прекрасный набор RetroPie, представляющий собой коллекцию эмуляторов разнообразных классических консолей и игровых автоматов, таких как Atari, Game Boy, MAME, Sega Megadrive, NES и SNES.

Установка не вызывает никаких осложнений и подробная описана. Стоит лишь отметить, что установить данную коллекцию можно двумя различными способами. Первый заключается в полной компиляции, всех эмуляторов входящих в состав из исходных текстов, а второй использовать перекомпилированные версии.

Первый раз когда я делал эксперимент, я использовал полную компиляцию и был несколько шокирован тем, что полная компиляция на моем Raspberry Pi заняла чуть более 6 часов, когда же второй раз я использовал уже перекомпилированные версии, то установка заняла немногим более получаса. В завершении установки стоит отметить опцию позволяющую автоматически запускать RetroPie при загрузке системы, тем самым избежав необходимости использовать клавиатуру для запуска в случае перезагрузки. Все действия внутри RetroPie можно производить классическим джойстиком.

Raspberry Pi

Немного об играх и как они попадают на мою приставку. Самым очевидным было бы использование сетевого ресурса, но эту идею я отбросил так как нашел куда более изящный способ. Для этих целей я использовал программу BitTorrent Sync, представляющую собой прекрасное средство для синхронизации файлов между компьютерами. Использую инструкцию с сайта Хабрахабр я настроил на синхронизацию директорию в которой RetroPie ищет rom‘ы c играми.

Далее я установил BitTorrent Sync на своем основном компьютере и теперь для закидывания игр в свою игровую консоль мне достаточно просто закинуть их у себя в папку локально, а она уже автоматически синхронизируется с директорией на моей малине. Время поиграть =)

Использование нескольких конфигураций Sphinx

Разрабатывая на одном хосте несколько сайтов с поддержкой Sphinx Search меня всегда раздражала невозможность использования несколько конфигурационных файлов одновременно единственным демоном Sphinx, а также отсутствие простых готовых решений для реализации подобного функционала.

К написанию своего решения этой проблемы меня подтолкнула заметка о том что в качестве конфигурационного файла можно использовать любой скрипт, в том числе написанный на bash‘е.

Для универсального комбинатора конфигурационных файлов использую типичную *nix структуру директорий:

/etc/sphinx/
    conf.d/
        100-example-domain.ru
        200-example-domain-2.ru
        999-searchd
    sphinx-config.bash

Где conf.d - директория с симлинками на конфигурационные файлы для индексов, а содержимое файла sphinx-config.bash

#!/bin/bash

WORKDIR=`dirname $0`
CONFDIR="$WORKDIR/conf.d/"

LINE=$(seq -s "#" 70 | sed 's/[0-9]//g')

if [ ! -d "$CONFDIR" ]; then
  echo "# Path '$CONFDIR' is incorrect."
  exit 1
fi

for file in "${CONFDIR%?}"/*
do
  if [[ -f $file ]]; then
    FILENAME=$(basename "$file")

    echo -e "${LINE}\n# Include file ${FILENAME}\n${LINE}\n"
    cat "$file"
  fi
done

Далее просто запускаю демона Sphinx, используя в качестве конфигурационного файла sphinx-config.bash.

/usr/local/sphinx/bin/searchd --config /etc/sphinx/sphinx-config.bash

Готовую реализация залил на GitHub sphinx-config-combinator.

Ребилд плеера AudioJS для Радио-Т

Некоторое время назад я делал форк плеера audio.js для проигрывания .gsm файлов. А теперь вот решил сделать еще один форк этого плеера но уже для сайта, популярного подкаста, Радио-Т.

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

audio.js Radio-T build

Скрипт уже работает на сайте подкаста Радио-Т, а исходный код и все инструкции по установке можно посмотреть и скачать на GitHub.

Raw GSM 6.10 Audio Stream проигрывание online

Столкнувшись с форматом Raw GSM 6.10 audio stream (.gsm) первый раз я решил пойти по пути наименьшего сопротивления и найти готовое решение для проигрывания таких файлов онлайн.

Наткнувшись на github на единственный вменяемый плеер под названием WavPlayer, поддерживающий формат Raw GSM 6.10 Audio Stream, я ужаснулся от его интерфейса да и написан он был на языке haXe. К счастью есть такой замечательный проект audio.js который представляет из себя симпатичный frontend JS плеер с backend кодеком на Flash.

Довольно быстро возникло желание совместить эти два проекта. Бегло осмотрев архитектуру плеера и api кодека, я отбросил всякое желание менять JS код плеера для совместимости с WavPlayer. Остался вариант переписать кодек, этим я и занялся.

До знакомства с WavPlayer я и понятия не имел о языке haXe на котором он написан. Посмотрев исходники кодека и почитав пару заметок на сайте языка haXe я довольно быстро освоил синтаксис который сильно напоминает ActionScript. Посидев несколько вечеров я закончил переписывание api, попутно исправив пару багов на которые автор явно забил, а может они проявляются только при проигрывании файлов gsm. Результатом всех усилий стал форкнутый проект, который можно посмотреть на github.

Сборка

Для самостоятельной сборки кодека необходимо установить haXe, скачать исходники кодека с github и скомпилировать командой:

haxe audiojs.hxml

В результате получится файл с названием audiojs.swf реализующий полный набор api методов которые необходимы для совместной работы с audio.js.

Готовый файл можно сказу скачать по ссылке.

Установка

  1. Устанавливаем скрипт audio.js
  2. Заменяем оригинальный файл audiojs.swf на новый
  3. А также в при инициализации скрипта необходимо указать в настройках useFlash: true.

Это необходимо чтобы флеш кодек использовался даже тогда когда браузер поддерживает формат audio тегов.

audiojs.events.ready(function() {
    audiojs.createAll({
      'useFlash': true // всегда использовать флеш
    });
});

Теперь для прослушивания online любой записи в формате .gsm достаточно вставить тег указывающий на файл. Например:

<audio src="test.gsm" />

Использование Sphinx для нахождения ближайших объектов по координатам

Для одного из проектов потребовалось реализовать программный функционал поиска ближайших объектов на карте в определенном радиусе от заданной точки с координатами широты и долготы. Такие задачи как правило требуют решения Прямой и Обратной геодезических задач, а поскольку с геодезией я совершенно не дружу, то обратил свое внимание на готовые решения, одним из который стал Sphinx.

Наверняка многие воспринимают Sphinx исключительно как полнотекстовый поисковый движок, я же хотел бы обратить внимание на магическую функцию @geodist, которую можно использовать для нахождения в индексе объектов на заданном расстоянии по их координатам (широте и долготе). Для нахождения ближайших объектов требуется не много:

  • База данных поддерживаемая Sphinx’ом с координатами объектов поиска
  • Установленный Sphinx Search
  • А также PHP + sphinxapi (или любой другой язык для которого есть sphinxapi)

База данных

Я не буду описывать процесс установки Sphinx’а на хостинг, мануалов в инете полно да и сам процесс установки банален и не требует каких-то особенных умений. Ниже привожу примерный файл конфига который понадобится для индексации таблицы с координатами объектов

# Источник данных для поиска
source main
{
    # параметры подключения к mysql
    type = mysql
    sql_host = localhost
    sql_user = user
    sql_pass = password
    sql_db = database
    sql_port = 3306

    # запросы после установки соединения
    sql_query_pre = SET NAMES utf8
    sql_query_pre = SET SESSION query_cache_type=OFF

    # не засыпать между шагами индексации
    sql_ranged_throttle = 0
}

# Источник данных для гео-поиска (наследует блок main)
source geo : main
{
    # запрос выборки широты и долготы в радианах для индексации
    sql_query = \
        SELECT `id`,
            radians(`latitude`), \
            radians(`longitude`) \
        FROM table_with_objects

    # обрабатывать поля как float
    sql_attr_float = latitude
    sql_attr_float = longitude
}

# настройка индекса
index geo
{
    # использовать соответствующий блок из source
    source = geo

    # путь для хранения файлов индекса
    path = /usr/home/www/sphinx/indexes/closest

    docinfo = extern
    mlock = 0
    min_word_len = 1
    charset_type = utf-8
}

# настройки демона
searchd
{
    # прослушивание порта
    listen = 9312

    # хранение логов
    log = /usr/home/www/sphinx/log/searchd.log
    query_log = /usr/home/www/sphinx/log/query.log
    pid_file = /usr/home/www/sphinx/log/searchd.pid
}

Индексация

При первоначальном запуске просто скармливаем созданных конфиг индексатору

indexer --config /usr/home/www/sphinx/sphinx.conf --all

Для переиндексации текущего индекса необходимо использовать параметр «–rotate», он добавит к созданному индексу новые данные

indexer --config /usr/home/www/sphinx/sphinx.conf --rotate

Запускаем демона

searchd --config /usr/home/www/sphinx/sphinx.conf

PHP + sphinxapi

Для проверки работы создадим простую форму

<form action="" method="get">
    Долгота <input name="longitude" size="40" value="<?=$_GET['longitude']?>"><br>
    Широта <input name="latitude" size="40" value="<?=$_GET['latitude']?>" /><br>
    Радиус <input name="radius" size="40" value="<?=$_GET['radius']?>"><br>
    <input type="submit" value="Искать!">
</form>

<?php
if(isset($_GET['longitude']) and strlen($_GET['longitude']) > 2)
{
    require_once('sphinxapi.php');

    function collectIds($arr)
    {
        return $arr['id'];
    }

    $_longitude = $_GET['longitude'];
    $_latitude = $_GET['latitude'];
    $_radius = (intval($_GET['radius']) > 0) ? intval($_GET['radius']) : 10;

    $search = new SphinxClient(); // Создание экземпляра клиента

    $search->SetServer("localhost", 9312); // Подсключаемся
    $search->SetMatchMode(SPH_MATCH_ALL); //
    $search->SetArrayResult(true); // Не использовать id документов в качестве ключей
    $search->SetLimits(0, 5); // Ограничить поиск 5 объектами
    $search->SetSortMode ( SPH_SORT_EXTENDED, "@geodist asc"); // Сортировать объекты по расстоянию от исходной точки поиска
    $search->SetGeoAnchor('latitude', 'longitude', deg2rad($_latitude), deg2rad($_longitude));

    $circle = (float) $_radius;
    $search->SetFilterFloatRange('@geodist', 0.0, $circle);

    $result = $search->Query('', 'closestStores');

    if($result AND $result['total'] > 0)
    {
        print_r($result);

        $ids = array_map('collectIds', $result['matches']);

        print_r($ids);
    }
}
?>

Если все настроено правильно, то под формой отобразится массив с результатами выборки.