1 ноября 2011, 16:53

GStreamer audio plugin для QNX

В процессе портирования WebKit в нашем проекте мне пришлось написать аудио плагин для GStreamer, который позволяет выводить звук в этом мультимедийном framework’е на qnx . На текущий момент мне известен только один выход для пользователей qnx — это использовать SDL gst plugin. Хотя как по мне — это совсем не элегантное решение тащить огромную библиотеку за собой ради простого вывода звука.

Поскольку в основу моего плагина лёг другой open source плагин (от него правда осталось не более 5% кода), то я в скором времени выложу исходники своего плагина на github, естественно предварительно убрав все проектно специфичные куски кода. Надеюсь моя работа будет кому-то полезна.

26 сентября 2011, 12:01

Rapoo E9080: Обзор очень компактной клавиатуры с тачпадом.

Rapoo E9080: очень компактная клавиатура с тачпадом.

Я не любитель писания обзоров железа, но поскольку я стал обладателем клавиатуры заслуживающей внимания, то посчитал, что надо поделится.

Задался я как-то поиском компактной беспроводной клавиатуры для своего HTPC и зашедши на ebay я нашёл прекрасную клавиатуру такую, какую я очень хотел. Rapoo не очень известный у нас китайский производитель, но забегая вперёд скажу, что я не в первый раз покупаю их продукты, и я постоянно доволен качеством их продуктов не смотря на репутацию китайских производителей. В данном случае — производитель серьёзно подходит к качеству своей продукции. Держать клавиатуру в руках приятно и чувствуется качество сборки.

Основные характеристики

Частота: 2.4GHz
OS: Windows XP, Windows 7, Mac OS X (мак ось я сам проверял, т. к. производитель умолчал о какой-либо совместимости)
Толщина: 5.6мм
Радиус: 10м
Приёмник: nano
Цена: ~50$

Комплектация

Клавиатура, нано приёмник, 2 батарейки ААА и документация.

Толщина

Толщина у клавиатуры действительно очень маленькая, всего 5.6мм, что сродни маковским алюминиевым клавиатурам.

Rapoo E9080: очень компактная клавиатура с тачпадом.

Rapoo E9080: очень компактная клавиатура с тачпадом.

Клавиатура

Пластик клавиш шершавый и очень приятный на ощупь. Дополнительные клавиши доступны через кнопку Fn. Скажу сразу: Fn расположена там где ей и место — между Ctrl и Win, что будет оценено почти всеми пользователями.

Ход у клавиш при такой толщине корпуса, конечно же короткий, ноутбучный. Тут никаких нареканий — приятно и комфортно работать (я вообще любитель короткого хода, так что это субъективно).

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

Rapoo E9080: очень компактная клавиатура с тачпадом.

Rapoo E9080: очень компактная клавиатура с тачпадом.

Тачпад

Тачпад выполнен из точно такого же пластика как и клавиши, что совсем не пошло ему на пользу — скользить пальцами по нему менее удобно чем, к примеру, на том же макбуке, где тачпад гладкий. Поэтому создаётся впечатление, что тачпад немного сопротивляется скольжению.

Rapoo E9080: очень компактная клавиатура с тачпадом.

Как можно заметить, на самом тачпаде нанесены символы дополнительной цифровой клавиатуры. Переключение между тачпадом и клавиатурой осуществляется слайдовым движением аля «айфон анлок» по надписи «SLIDE HERE». После чего возле слайдера 3-4 раза мигнёт светодиод сообщающий о переключении. Никакой другой индикации на клавиатуре нет. Если вы забыли в каком режиме вы оставили клавиатуру, в тачпаде или в режиме клавиатуры, вспоминать прийдётся только экспериментальным путём.

Тачпад распознаёт следующие жесты:

Один палец — управление движением курсора мышки.
Два раза стукнуть пальцем — щелчёк левой кнопкой мышки.
Касание тремя пальцами — щелчёк правой кнопкой мышки (слегка не удобно).
Два пальца — скроллирование (я смог заставить работать только вертикальную прокрутку).

Обратите внимание: распознование жестов и касаний несколькими пальцами реализовано ПО встроенным в клавиатуру! Т. е. windows ничего не знает о том, сколькими пальцами были сделаны нажатия и как вы ими скользили по сенсорной панели. Из этого следует только один вывод: вы никак не сможете переназначить жесты или изменить их значение — они вшиты в клавиатуру. Windows считает что получает сигналы от обычной мышки — поэтому об расширении сенсорного функционала и распозновании новых жестов можно, увы, забыть.

Поскольку никаких дисков и утилит в поставке не шло, то и настраивать тачпад можно только стандартными утилитами операционной системы. А настраивать многим вероятно прийдётся, т. к. на мониторах 1900х1200 курсор двигается не так быстро как хотелось бы. За одно касание курсор с одного края экрана в другой не успевает передвинуться и требуется 2-3 касания чтобы сделать это. Вполне вероятно, что на мониторах поменьше настройка скорости курсора может не понадобиться.

Ресивер

Тут сказать особо нечего — стандартный нано-ресивер.

Rapoo E9080: очень компактная клавиатура с тачпадом.

Обратная сторона

Обратная сторона клавиатуры выполненна из металла на котором очень аккуратно выгравированы логотип производителя и значки соответствия стандартам. Металл очень маркий и следы на нём остаются мгновенно, а оттираются достаточно сложно. Сам металл выглядит очень солидно за счёт аккуратной и не броской текстуры.

Rapoo E9080: очень компактная клавиатура с тачпадом.

Батарейный отсек

Батареи используются формата AAA (маленький «пальчик»). Как было сказано в начале — батарейки входят в комплект поставки.

Рядом с батарейным отсеком есть место для ресивера. Там же рядом располагается переключатель включения питания. Больше никаких других кнопок и рычажков нету (например сброс или соединение как в клавиатурах Logitech).

Rapoo E9080: очень компактная клавиатура с тачпадом.

В интерьере

Rapoo E9080: очень компактная клавиатура с тачпадом.

Rapoo E9080: очень компактная клавиатура с тачпадом.

Впечатления

Впечатления как я уже говорил — положительные. Единственный небольшой минус — это не слишком скользкая поверхность тачпада. По большому счёту недостатоков у клавиатуры нет, но вот использовать её с тачпадом как полноценный рабочий инструмент 8 часов в день, без мышки — будет сложновато, это всё же не эппловский тачпад с широким функционалом. Но вот как дополнительная клавиатура (для HTPC как в моём случае) она в самый раз.

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

Предугадывая возможный вопрос: статистикой по долговечности работы от батареек я не обладаю, т. к. клавиатура у меня всего второй день.

Добавлено месяц спустя

После месяца использования клавиатуры, могу сказать, что она просто нормальная. Не плохая, не отличная, а нормальная. Я разбалован тачпадами Apple, вот они — отличные. Я же эту клавиатуру использую только с FullHD телевизором и лично мне не хватает быстроты курсора — двигать курсор в разные части экрана приходится за несколько касаний, т. е. быстро метнуться из одного края в другой — не получится. Если надо сделать что-то быстро, то это слегка раздражает. Моя жена вообще со своими ногтями очень нервничает — аккуратно работать ей очень сложно. Так же иногда бывают ложные срабатывания, но это больше случается тогда, когда забываешься и случайно касаешься тачпада пальцем или ладонью — это минус того, что тач в непосредственной близости от клавиатуры. Ну и относительно шероховатости тачпада: было бы намного лучше с более гладкой поверхностью.

В качестве основного рабочего инструмента (если вы работаете за клавиатурой 6-8 часов) — использовать не советую: я подозреваю, что досадные мелочи с тачпадом тут же превратятся в серьёзные недостатки и будут портить нервы. [Добавлено ещё через пару недель: довелось поработать целый день с клавиатурой переустанавливая систему. Использовать её всё же очень сложно из-за огромного количества ложных срабатываний тачпада — руки попадая в ту часть клавиатуры (курсорные клавиши, клавиша Enter) часто цепляют тачпад и курсор мыши на экране начинает творить мелкие пакости которые изрядно раздражают.]

К клавиатуре вопросов нет, но замена мышки сенсорной панелью в этом случае не пройдёт. Дизайнерам и художникам этот продукт я совершенно не рекомендую. Даже на эппловских тачпадах работать в графических редакторах очень сложно (проверено лично), а с этим тачпадом можно вообще загреметь в больницу с расшатанной психикой и нервными срывами. Он попросту не проектировался для такого. Так к примеру тут нет возможности «перехватывать» объекты. Перехватом я называю момент, когда надо перетащить объект на большое расстояние (файл к примеру), но дотащив «объект» до края тача дальше двигаться не можешь, тогда ставишь второй палец в начало тача и продолжаешь тянуть дальше — именно так реализовано в тачах от Apple. Тут, увы, такого нет и в помине. Тут реализован очень и очень простой тач (Apple не зря покрыла патентами свои разработки в области сенсорных технологий). Да и Windows совсем не touch ориентированная система в отличие от Mac OS X, в которой без тача уже сложновато. Это тоже играет свою роль в удобстве использования.

Есть ещё один неудобный момент. Если клавиатуру не использовать 1-2 минуты, то она впадает в режим сна с пониженным энергопотреблением, тачпад перестаёт функционировать и не реагирует на касания, пока любая из клавиш не будет нажата. Таким образом, к примеру, вывести компьютер из режима энергосбережения просто касанием к тачпаду (по аналогии с мышкой) — нельзя. Но я для себя уже приловчился выводить клавиатуру из сна нажатием кнопки Fn — это самая безопасная кнопка и не произойдёт ненужных действий.

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

23 августа 2011, 18:40

Как определить, что клиент закрыл соединение

Мне тут на днях потребовалось в клиент-серверном коде моментально определить, закрыл ли клиент соединение или оно всё ещё держится. Решение требовалось сделать как на .NET так и на POSIX с помощью обычного C. Быстрый анализ различных документаций показал, что решения «в лоб» в виде вызова некоторой функции аля «getConnectionState(soket)» просто не существует ни в posix, ни в .NET.

Самое интересное, что по спецификации TCP этот протокол позволяет вполне точно определить когда клиент отсоединился. Речь конечно идёт о корректном завершении соединения, а не о физическом обрыве связи которое нельзя определить штатными средствами tcp протокола.

Требование к задаче следующее:
  1. Должна быть функция которая гарантированно получает N байт из сокета.
  2. Функция должна без промедлений определять отвалившегося клиента.
  3. .NET C# версия должна выбрасывать свой ConnectionLostException в случае разрыва соединения.
  4. POSIX C/C++ версия должна возвращать количество полученных байт или ноль в случае разрыва соединения.
Решение конечно же есть, но для этого требуется задействовать вспомогательную функцию poll(). Эта функция существует как в обычной posix среде, так и в .NET, и имеет одинаковое название в обоих случаях. Разница лишь в том, что в .NET среде она сугубо сокетная, а в posix ею можно любые файловые дискрипторы обрабатывать. Необычность этой функции заключается в том, что определение разрыва соединения это её далеко не основная задача. Этой функцией можно определить разные состояния/события сокета (для .NET) или файлового дискриптора (для posix). По большому счёту эта функция — слуга двух господ, т. к. в разные моменты времени в зависимости от контекста она сигнализирует о совершенно разных событиях в сокете/дискрипторе.

В нашем частном случае после того как соединение было успешно установлено, poll() возвращает true/non zero если сокет имеет данные, либо соединение разорвано (наша задача затем определить что именно произошло: пришли данные или соединение закрыто). В противном случае по таймауту возвращает false/zero (т. е. за время таймаута событий в сокете не случилось). Если к примеру сокет находится только в состоянии установки соединения, то результат возвращённый poll() будет указывать на другие события связанные с сокетом. Это стоит помнить.

Теперь код.

C#:
  1. static public void ReceiveBytes(Socket sock, byte[] data)
  2. {
  3.     int totalReceived = 0;
  4.     int size = data.Length;
  5.  
  6.     // Цикл до тех пор пока не получим все данные
  7.     while (totalReceived < size)
  8.     {
  9.         // Ждём 0.1 секунду события: или новые данные или обрыв
  10.         if (sock.Poll(100000, SelectMode.SelectRead))
  11.         {
  12.             // Проверяем есть ли какие-то данные у сокета для нас
  13.             if (sock.Available == 0)
  14.             {
  15.                 // Данных нет, но раз Poll() вернул true — это обрыв
  16.                 // поэтому бросаем свой ConnectionLostException
  17.                 throw new ConnectionLostException();
  18.             }
  19.             try
  20.             {
  21.                 // Получаем данные
  22.                 totalReceived += sock.Receive(data, totalReceived /* offset */,
  23.                                              size - totalReceived /* size to recieve */,
  24.                                              SocketFlags.None);
  25.             }
  26.             catch (SocketException ex)
  27.             {
  28.                 // В зависимости от того как сконфигурирован сокет
  29.                 // мы можем поймать таймаут или попытку заблокировать сокет
  30.                 if (ex.SocketErrorCode == SocketError.TimedOut ||
  31.                    ex.SocketErrorCode == SocketError.WouldBlock)
  32.                 {
  33.                     // Это не критично и мы продолжаем цикл
  34.                     continue;
  35.                 }
  36.                 else
  37.                 {
  38.                     // Остальные исключения говорят о какой-то ошибке
  39.                     break;
  40.                 }
  41.             }
  42.         }
  43.     }
  44. }
  45.  

С/С++:

  1. int recieveData(int socket, void * buffer, int size)
  2. {
  3.     int totalRecieved = 0, arrived = 0;
  4.     struct pollfd pfd;
  5.  
  6.     // Подготавливаем структуру для вызова функции poll()
  7.     pfd.fd = socket; // Указываем дискриптор сокета который интересует
  8.     pfd.events = POLLIN | POLLHUP | POLLRDNORM;
  9.  
  10.     // Цикл пока не получим все данные
  11.     while(totalRecieved < size)
  12.     {
  13.         // Ожидаем событие в сокете с таймаутом 100 миллисекунд
  14.         if(poll(&pfd, 1100) > 0)
  15.         {
  16.             // Произошло какое-то событие — пытаемся получить данные
  17.             arrived = recv(socket, (char*)buffer + totalRecieved, size - totalRecieved, MSG_DONTWAIT);
  18.  
  19.             // Если данных не пришло после того как poll() вернул не нулевой
  20.             // результат — это означает только обрыв соединения
  21.             if(arrived == -1 || totalRecieved == arrived)
  22.             {
  23.                 // Сбрасываем счётчик полученных данных, что скажет об разрыве соединения
  24.                 totalRecieved = 0;
  25.                 break;
  26.             }
  27.  
  28.             // Продолжаем получать данные
  29.             totalRecieved += arrived;
  30.         }
  31.     }
  32.  
  33.     return totalRecieved;
  34. }
  35.  

Приведенный выше код прекрасно отрабатывает и мгновенно отлавливает ситуации когда клиент закрывает соединение.

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

Happy coding! =)
posix   net   c&cpp   c#

2 августа 2011, 16:58

Aperture 3 и линейный DNG

Вполне вероятно, что если бы в мире не было проблем, то и писать было бы не о чем. =) В общем есть у Apple Aperture 3 два недостатка, которые омрачили мне впечатление от программы. Первый — программа из рук вон плохо поддерживает поиск на русском языке (Вася ≠ вася), а с нечётким поиском совсем худо. Второй недостаток многие вероятно никогда даже и не заметят, уж очень он специфический. Проявляется он только в связке Aperture 3 + DNG + (плёночный) сканер. Однажды домой ко мне попал плёночный сканер с помощью которого я отсканировал несколько цветных плёнок. Результат работы вышел на многие гигабайты, т. к. софт сканера умел сохранять 16-битные сканы только в TIFF. Чтобы хоть как-то вернуть украденное таким расточительством место — решил перегнать tiff в dng. Само конвертирование не заняло много времени, а вот попытка загрузить получившиеся dng файлы в Aperture 3 неожиданно провалилась. Aperture упорно ругалась на то, что «извините, но линейные DNG мы не кушаем». Это что ещё такое?

Сходил на сайт технической поддержки Apple — не помогло. Интернеты так же молчали. В итоге после нескольких экспериментов я всё же пришёл к выводу в чём загвоздка.

Aperture прекрасно открывает dng файлы полученные из raw фотографий с цифровых фотокамер и напрочь отказывается от dng созданных после сканирования. Значит разница в том, как хранятся пиксели внутри dng. Тут я вспомнил о том, что у цифровых камер RGB пиксели матрицы располагаются особым образом (фильтр Байера):

Aperture 3 и линейный DNG

Этот формат используется большинством камер (кроме Sigma c их X3 Foveon матрицами и некоторыми Fuji на сколько мне известно). А сканер в силу иной природы получения картинки создаёт линейную картинку:

Aperture 3 и линейный DNG

Сама спецификация dng определяет, что внутри dng файла картинка может быть сохранена в любом из этих форматов, а вот купертиновцы похоже подумали «99% камер использует формат пекселов на основе Байера. Если кто-то и конвертирует в формат DNG, то только из raw формата камер. Так зачем какие-то редкие линейные форматы поддерживать в dng?» и отбросили поддержку. Другого объяснения для себя не нашёл. С одной стороны — они съэкономили время на разработке, а с другой сделали кривую поддержку открытой спецификации.

По итогу окончательного решения нет. Если вам довелось с этим столкнуться — ищите обходные пути: используйте другой формат или другую программу. Если не принципиально — используйте Adobe Lightroom, там поддержка dng отличная. Если принципиально, то можете сохранить не в dng, а в psd — он более менее нормально поддерживается Aperture.

Happy using! =)

17 июля 2011, 18:08

Возможно самое короткое преобразование в bool

В нашем текущем проекте мы портируем WebKit под проект заказчика и приходится крайне много копаться в эппловском WebKit’е и немного в гуглевском Chromiume. Сколько бы я не занимался C++ , я постоянно нахожу что-то интересное. Поскольку chromium пишут достаточно серьёзные спецы, то я периодически наталкиваюсь на занимательные (на мой взгляд) куски кода на которых можно поучиться.

Так например совсем недавно я увидел выражение вида:

return !!count;

В первую секунду было удивление, а в следующую секунду стало понятно, что эта запись преобразует любое числовое значение к bool. Очень лаконично и красиво как по мне, вместо привычного:

return (bool)count;

В принципе такое преобразование должно так же работать в java, c#, да и наверное во всех производных от С языках.

Happy coding! =)
Заметки     ←  следующие     Ctrl     предыдущие  →