Инструменты пользователя

Инструменты сайта



// Обновление в статьях

Изрядно обновил статью Linux, ThinkPad T530 и miniDP (displayport), поместил ссылку на неё в Статьи. Если коротко: то в общем и целом настройка чуть упростилась и улучшилась. Но дёготь остался, куда без него.

// Топлёное масло

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

// Awesome C++

Вырвано из G+:

С сайта:

A curated list of awesome C/C++ frameworks, libraries, resources, and shiny things

Систематизированный список библиотек для решения различных задач на C++. Пока ограничен битбакетом и гитхабом, поэтому добавить некоторые полезные библиотеки за пределами этих площадок пока (?) возможности нет.

Список раньше хостился на GitHub, теперь обрёл второе рождение в виде сервиса.

Система рейтингов и меток должна помогать выбирать полезное. Как будет работать на самом деле - покажет время.

В подвале сайта смотреть подобные каталоги для других языков, в частности, Rust и Go.

// Две Икрянки и немного Партизанского хребта

На первомайские планировали сходить немного траверса по Партизанскому хребту с заходом на г.Синяя. Заход: по р.Икрянка от села Ястребовка. Выход: р.Правая Икрянка в село Ястребовка.

// Хранение перезаправленных картриджей ручек Platinum

Пост для истории. Основные посылы, которые «не позволили» мне воспользоваться конвертером для ручки Platinum Balance можно почитать на penmania.ru.

Перезаправка картриджа не более грязная или долгая работа (наоборот, показалось, что выходит более чисто и быстро) чем заправка конвертера ручки. Но меня мучал вопрос хранения уже заправленных картриджей, ведь в этом случае проблема перезаправки становится ещё менее выраженной: при большей ёмкости и N-ном количестве картриджей шприц для заправки и бутылёк чернил можно хранить только дома и не носить с собой вообще.

// std::string_view и временные объекты

Идея поста родилась при употреблении чая во внутрь на южной кухне.

Недавно смотрел один доклад (точнее бегло просматривал) про Rust и в момент, когда начался рассказ про life-time, глаз зацепился за такой опасный пример из мира C++:

string get_url()
{
  return "http://htrd.su";
}
 
string_view get_schema(string_view v)
{
  // тут какие-то действия, я их опущу
  auto result = v;
  return result;
}
 
int main()
{
  auto v = get_schema(get_url());
}

Что такое string_view - смотреть тут или тут. Если коротко - это невладеющая строка. Полезна для экономии на аллокациях, когда нужно работать с частями исходной строки.

В общем, из природы string_view следует и проблемы в коде выше: get_url() вернёт временный объект, который будет уничтожен в конце выражения, а следовательно, v будет ссылаться на невалидный участок памяти.

У меня в голове родилось, сходу, вариант защиты от такого: так как string_view не владеет строкой, то перемещение для строки сделать невозможно (да и семантически неверно), а перемещающий конструктор будет предпочтён для временного объекта. Следовательно если сделать перемещающий конструктор для string у string_view удалённым, то код выше сломается на этапе компиляции.

// C++ и 2D графика

Навеяно.

Из того, что мне понравилось:

    • Язык: C
    • Реализация: библиотека
    • Реально проста для простых применений. Куча примеров и статей в интернете. Поддерживает достаточно большое число платформ и компиляторов.
    • Язык: C++
    • Реализация: header-only
    • Библиотека отличается феноменальной простотой установки: только один заголовочный файл и всё. Минусом будет только тот факт, что нужно будет указать правильные флаги линковщика для целевой платформы. Но при этом весь базовый функционал для рисования и процессинга изображений присутствует. Дружится с OpenCV. Думаю, стоит рассматривать вариант этой библиотеки, когда нужно что-то по-быстрому нарисовать.
    • Язык: C++
    • Реализация: библиотека
    • С данной библиотекой особо не имел дел. Но примеры представляют её эдаким вариантом SDL, но на C++. Стоит попробовать.

Кроме того, на ресурсе cppreference.com есть свой список библиотек под различные задачи (в дополнение к предыдущему посту), и, в частности, для графики.

ЗЫ по ссылке выше есть интересная библиотечка для пользовательского интерфейса (GUI): nana, стоит пощупать. А так же для TUI: cwidget.

ЗЗЫ прочие ссылки:

// Коллекция ресурсов по современному C++

На RSDN промелькнуло, может ещё кому полезно будет:

Кто хочет дополнить - шлите мёрж-реквесты.

Прочие полезные ссылки, спасибо @sikmir:

// Полезные алиасы для программиста

Пока речь пойдёт про алиасы (alias) для man. Потом, может быть, что-то будет дополнено.

MAN

Часто возникает вопрос: «man чаво?». Кроме того, интересные программистам документы, обычно, находятся в секциях 2 (системные вызовы), 3 (библиотечные вызовы) и 7 (стандарты, соглашения, обзоры). По назначению других секций можете спрашивать:

  man # intro

где # - номер секции от 1 до 7.

В общем родилось три алиаса: для обращения и для поиска.

Для использование, код ниже поместить в ~/.bashrc

alias man-prog='man -s 2,3,7'
alias man-prog-search='man -s 2,3,7 -K'
alias man-prog-apropos='man -s 2,3,7 -k'

Первый - просто ограничивает область поиска и по man-prog printf выведет не описание команды, а описание функции.

Второй - обеспечивает полнотекстовый поиск по страницам, третий - по индексу (apropos). В чём разница. Поясню на примере:

$ man-prog-apropos tcp
clnttcp_create (3)   - library routines for remote procedure calls
clock_getcpuclockid (3) - obtain ID of a process CPU-time clock
getcpu (2)           - determine CPU and NUMA node on which the calling thread is running
pthread_getcpuclockid (3) - retrieve ID of a thread's CPU time clock
QwtCPointerData (3)  - (неизвестный объект)
sched_getcpu (3)     - determine CPU on which the calling thread is running
svctcp_create (3)    - library routines for remote procedure calls
tcp (7)              - TCP protocol
zmq_tcp (7)          - 0MQ unicast transport using TCP

Вроде всё хорошо. Дальше:

$ man-prog-apropos TCP_CORK
TCP_CORK: ничего подходящего не найдено.

Оппа… В гуголь лезть? А если так:

$ man-prog-search TCP_CORK
--Man-- след: sendfile(2) [ просм (ввод) | пропуск (Ctrl-D) | выход (Ctrl-C) ]
--Man-- след: sendfile64(2) [ просм (ввод) | пропуск (Ctrl-D) | выход (Ctrl-C) ]
--Man-- след: sendmsg(2) [ просм (ввод) | пропуск (Ctrl-D) | выход (Ctrl-C) ]
--Man-- след: sendto(2) [ просм (ввод) | пропуск (Ctrl-D) | выход (Ctrl-C) ]
--Man-- след: splice(2) [ просм (ввод) | пропуск (Ctrl-D) | выход (Ctrl-C) ]
--Man-- след: tcp(7) [ просм (ввод) | пропуск (Ctrl-D) | выход (Ctrl-C) ]

в man 7 tcp мы найдём искомое описание.

// std::cout, std::cerr и std::clog

Сначала немного информации из мира С.

При запуске приложения (речь идёт о POSIX) вместе с ним открывается 3 файловых дескритоптора:

  • 0 - ассоциирован со стандартным вводом (stdin)
  • 1 - ассоциирован со стандартным выводом (stdout)
  • 2 - ассоциирован со стандартным выводом в поток ошибок (stderr)

В стандартной библиотеки Си используется FILE*-based буфферизируемый доступ к файлам и терминалу. В stdio.h объявлены следующие глобальные символы, которые отражают стандартные потоки ввода вывода:

  • stdin
  • stdout
  • stderr

Соответственно их свободно можно использовать вместе с семейством функций fread()/fprintf(), обеспечивая буфферизированный доступ.

Сами файловые дескрипторы POSIX объявляет через макросы в unistd.h:

  • STDIN_FILENO
  • STDOUT_FILENO
  • STDERR_FILENO

Соответственно их свободно можно использовать со всем семейством функций read(), write() и, даже, select()/epoll() и fcntl() (например, при помощи fcntl(O_NONBLOCK)+select+read можно реализовать аналог getch() из старого доброго Borland C++). Доступ через эти функции не буфферизирован.

Доступ к одному потоку разными механизмами в одной программе лучше не осуществлять: буферизация это уровень библиотеки C и внутреннего устройства FILE. write() или read() ближе к системным вызовам и ничего про это знать не обязаны. Как результат можете получить перемешивание текста даже в однопоточном приложении. Это не отменяет того файла, что сам fwrite() может, в конце концов, вызвать write().

На этом экскурс закончим и вернёмся в C++.

В C++ для работы с потоками служит библиотека iostream. Причём доступ к конкретному стриму может быть как буфферизируемым так и не буфферизируемым (зависит от потребностей).

Библиотека декларирует объекты, связанные со стандартными потоками:

  • std::cin - стандартный ввод
  • std::cout - стандартный вывод
  • std::cerr - стандартный вывод ошибок и
  • std::clog - для логирования

Про std::cin особо гооврить (пока?) не будем - он один, в своём роде. А вот про оставшиеся три стоит.

Итак, начнём с std::cout и std::cerr. В C++ они, помимо того, что связаны с разными дескрипторами, несколько отличаются поведением:

  • std::cout - буферизируемый
  • std::cerr - не буферизируемый

Такое отличие явственно следует из семантики использования: ошибку нужно увидеть сразу без ожидания каких-то дополнительных действий со стороны программиста типа std::flush или std::endl (он, кстати, делает и flush, поэтому, для большей производительности строки в нормальном выводе стоит заканчивать '\n', а не std::endl).

Ок, а что за std::clog? А это всего-лишь std::cerr + буферизация. И снова, семантика использования проста: диагностика может чуть и подождать, что бы не понижать производительность вывода, но смешиваться с нормальным выводом не есть хорошо, мы, ведь, можем использовать приложения в пайпе и, желательно, разделить диагностику и ошибки от обычного вывода.

Собственно, немного обобщая:

  • std::cout - используется для обычного вывода результатов работы программы на экран, эти данные могут быть переданы дальше по пайпу для обработки.
  • std::cerr - вывод сообщений об ошибке в обработке, что бы не подмешивались в основной поток и не ломали логику работы других программ в пайпе. При этом сообщение выводим максимально скоро.
  • std::clog - используем для разного рода диагностических сообщений, но когда использование std::cerr замедляет вывод из-за более частого дёргания системных вызовов, при этом, не подмешиваемся в основной поток и не мешаем работе других приложений в пайплайне.

Хорошим тоном, так же, является вывод справки по программе в std::cout, если вызвано с параметрами -h|–help - тогда её удобно смотреть в, например, less без дополнительных телодвижений, а вот справку по опциям, в случае неправильной установки какого-то параметра (или пропуска обязательного), лучше выводить (тут особой разницы не вижу) в std::cerr или std::clog.

И, на последок, лекция по поводу тормозов iostream и вообще, а как оно там внутри устроено:

// Source Specific Multicast и Asio

Недавно на ru.SO проскочил вопрос: как можно подключиться к SSM (Source Specific Multicast) группе?

Нюанс в том, что для этого используется опция `MCAST_JOIN_SOURCE_GROUP` для которой нет объекта-обёртки. Но, как оказалось, такой объект пишется самостоятельно на раз-два. Под катом я продублирую свой ответ, как пример подхода реализации нужного функционала. Пример не самый идеологически правильный, но, как оказалось, рабочий. Автор сам предложил свой вариант с захватом сырого хендла. Такой подход тоже имеет смысл в некоторых ситуациях9).

9) у меня случилось однажды так подружить сетевые абстракции Asio и libev, реализовав, тем самым, реактор на Asio :-)

// С юга на север по Ливадийскому хребту

23 февраля решили отпраздновать очередным снегоступингом.

По предложению Кирилла рассматривали варианты посещения южных отрогов Ливадийского хребта.

Маршрут изначально рассматривался как:
Фокино-г.Халаза-г.Горбуша-г.Лысый дед-Молёный мыс
но в результате был скорректирован до:
Душкино-падь Светланка-г.Круглая-г.Пидан-Лукьяновка.

Собралось три человека: я, Кирилл, Саня. В роли адового тропильщика в этот раз Кирилл.

// GeoCrop 1.0

Я подумал и решил, что функционала и стабильности достаточно для релиза версии 1.0.

Так что да будет так: https://github.com/h4tr3d/geocrop/releases/tag/v1.0

// GeoCrop и популярные привязки

Если у вас на входе привязанный GeoTIFF, то проблем нет никаких, но если у вас просто растр (.png, .jpeg, .gif) и привязка для него, то есть нюансы. Вообще, GeoCrop умеет работать с любыми данными, с которыми умеет общаться GDAL. Но в в некоторых случаях не всё получается гладко, так, например, только сегодня он научился читать файл проекции для world-привязок (пара .prj+.pgw).

На просторах интернета можно встретить различные описания привязок, самые популярные:

  • Ozi Explorer
  • World files10)
  • Global Mapper

рассмотрим более подробно.

Ozi Explorer

GDAL не умеет только шифрованные OZFX, а так привязанная карта представляет собой пару .map+растр, где растр - это, обычно, .gif, .jpg или .png, реже - .bmp. При наличии такой привязки geocrop можно вызвать без дополнительных приготовлений:

geocrop -f VRT -s 50k K-53-026-A.map K-53-026-A.vrt

Обратите внимание, что передаётся map файл, а не растр.

World files

Т.к. сама привязка состоит из двух файлов (.prj+.pgw), то не так просто сказать, что и откуда читать. Согласно документации .pgw, .pngw или .wld файл11) подтягивается автоматически, если на входе карта в PNG (про другие форматы - ниже), а вот .prj файл нужно читать самому. Для этого в последней версии GeoCrop сделана небольшая эвристика:

  • Если растр содержит пустую проекцию, то производится попытка прочитать проекцию (формат WKT или PROJ.4) из файла с таким же именем, но расширением .prj и .prf.
  • Либо файл проекции можно жестко задать при помощи новой опции -p srs_def

Т.е. при наличии привязки в виде world files GeoCrop так же можно вызвать без дополнительных приготовлений так:

geocrop -f VRT -s 50k K-53-026-A.png K-53-026-A.vrt

если файл проекции находится в K-53-026-A.prj или K-53-026-A.prf, или так:

geocrop -f VRT -s 50k -p K-53-026-A.wkt K-53-026-A.png K-53-026-A.vrt

Обратите внимание, что в обоих случаях в качестве входного источника передаётся сам растр, а не его привязка.

Если у вас растры отличные от PNG:

  • BMP - привязка ищется в .bpw, .bmpw или .wld.
  • GIF - привязка ищется в .gfw, .gifw или .wld.
  • TIFF - если это GeoTIFF со встроенной привязкой, то она и используется, если это просто растр, то привязка ищется в .tfw, .tifw/.tiffw или .wld, а так же в MapInfo .tab файле.
  • JPEG - привязка ищется в .jgw, .jpgw/.jpegw или .wld, а так же MapInfo .tab файле.

Полный и актуальный список всегда можно посмотреть тут: http://www.gdal.org/formats_list.html

Global Mapper

В данный момент GDAL не поддерживает данный формат, а значит не поддерживает и GeoCrop. Ищите способ как сконвертировать его во что-то удобочитаемое.

Вообще .gmw файлы достаточно простые для разбора, так что, возможно, появится у меня и их поддержка. Тем более, что для тех же карт GGC там сразу зашита информация об обрезке (только странно, что они сразу не сделали рамку прозрачной).

// Новый режим в GeoCrop

Теперь в GeoCrop появился новый режим: генерация полигона для обрезки рамки в формате CSV+WKT. Вывод на stdout, так что можно сохранить в любой удобный файл из скрипта, после чего использовать как аргумент для -cutline у gdalwarp в какой-то более сложной команде. Вызова gdalwarp при этом не происходит.

Активируется режим опцией -g (от [g]enerate). Указывать выходной файл при этом не нужно - он будет проигнорирован.

Так же, теперь появилась возможность указывать файл с описанием проекции: -p srs_file. Сама проекция должна быть в формате WKT или PROJ.4. Эта опция перезаписывает определение проекции в текущем файле. Полезна для преобразования файлов с привязками в виде world-файлов. Более того, если проекция в файле пустая, а опция не указана то произведётся попытка прочитать её автоматически из файла с таким же именем, но с расширением .prj или .prf (какой первый попадётся). Так что популярные карты ГГЦ с такими привязками теперь можно конвертировать так же просто, как и с привязками Ozi Explorer.

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

geocrop -f VRT -s 200k K-53-07.map K-53-07.vrt -- -overwrite

опция -overwrite будет передана gdalwarp. Помимо этого, теперь можно переопределить и сам исполняемый файл gdalwarp - опция -w GDALWARP.

Кроме того изменился формат опций, стало возможным указывать выходной формат (опция -f FMT, как следствие, образовались такие возможности: Быстро и ненавязчиво готовим карту для открытия в QMapShack) или только обрезать рамку, не делая кроп (опция -n).

// Быстро и ненавязчиво готовим карту для открытия в QMapShack

Для примера будет рассмотрен сервис http://loadmap.net, который предоставляет карты с привязками в формате OziExplorer.

Минусом подобных карт бывает то, что у них есть рамка и отдельные листы карт перекрывают друг друга при открытии. Для того, что бы рамку резать я уже написал ранее12) про свою программку geocrop.

Теперь про самый смак: QMS умеет открывать .vrt файлы. VRT файл это XML документ, с описанием привязки и различных преобразований, понятные движку GDAL. Так вот, в ходе беглого исследования оказалось, что мой способ резки рамки применим к VRT файлам: данное преобразование просто сохраняется внутри и применяется при открытии! Если добавить сюда тот факт, что переконвертации самого растра не происходит и просто формируется дополнительный маленький XML файл, то счастье становится полным.

Рассматривать вопрос сборки программы я подробно не буду, скажу только, что нужны dev пакеты для libgdal и libproj4. Устанавливать программу не нужно - просто скопируйте в удобное место, у меня это ~/bin. Сборка и работа на Windows не проверялась.

Вот, преамбула завершилась… Основная часть будет короче :)

  1. Скачиваем растровый файл карты, допустим это 500-метровка K-53-027-A, тогда файл будет K-53-027-A.png
  2. Скачиваем файл привязки K-53-027-A.map
  3. Обрезаем рамку и формируем VRT:
    ~/bin/geocrop -s 50k -f VRT K-53-027-A.map K-53-027-A.vrt

    Обратите внимание на параметр -s - он задаёт масштаб листа в виде делителя, т.е. опущена 1:, а буква обозначает степень десятки на которое нужно домножить: 50k (кило) = 50 * 10^3 = 50000 и масштаб тогда 1:50000, т.е. пятисотметровка.

12) ozi2map от туда более не актуальна

// QMapShack

Внезапно QMapShack стал юзабельным!

Но немного истории. QMapShack это революционное развитие QLandkarteGT от того же автора. Просто архитектурно QLandkarteGT перестал соответствовать требованиям.

Итак, как минимум следующие фичи теперь доступны в QMS (принятая аббревиатура для QMapShack в расслылке)13):

  • Открытие серии файлов с геоданными, переданных, как аргументы приложения. Это не относится с картам (?) - они берутся только из директорий, которые вы настроили в программе (аналогично произвольная карта не может быть открыта через File → Open Map, такого пункта просто нет).
  • Поддерживаются ВСЕ форматы карт, которые поддерживаются GDAL (!). Но делается это не напрямую, а через формирование .vrt файла. Сей унифицированный способ отменил отдельное открытие GeoTIFF - теперь нужно и для него формировать vrt-файл. К счастью теперь это делается через внутренний инструмент vrtbuilder и позволяет в большинстве случаев обойтись без утомительной конвертации в GeoTIFF, например привязок OziExplorer14)15). Вообще список теперь достаточно вменяемый:
    • Векторые карты:
      • .img - веркторные карты Garmin в non-NT формате. NT-формат не поддерживается и поддерживаться не планируется.
    • Растровые карты:
      • .vrt - враппер для всех типов GDAL.
      • .jnx - Garmin Birds Eye.
      • .rmap - CompeGPS Map Container
    • Онлайн карты:
      • .wmts - WMTSCapabilities.xml с любого картографического сервера, переименованный в уникальное имя. Дальше есть подробности.
      • .tms - описание правил использования TMS серверов. Через такие файлы можно подключить всякие OpenStreetMap, OpenCycleMap и так далее. Встроенный мастер позволит сгенерировать такие файлы для некоторых популярных сервисов.
    • DEM рельеф:
      • .vrt - как и прочие растровые карты
  • (!) Более развитые средства управления геоданными. Каждый файл GPX воспринимается как отдельный контейнер-проект. Данные между ними можно копировать. Теперь можно объединить несколько треков в один (!).
  • (!) Больше информации по трекам: можно задать тип активности, можно посмотреть графики высоты от расстояния, скорости от расстояния, или прогресса пути от времени.
  • (!) Более развитые средства редактирования треков. Правда точки так и не удаляются, но можно скрыть их, спрямив, например, трек (убрав топтание на месте, при остановке на обед или заделку колеса на велосипеде).
  • (?) Более активное использование мыши в окне отображения карты. В контекстном меню находится большинство полезных пунктов, типа создания путевой точки или трека. Да и вообще больше динамики в интерфейсе, точнее в области карты.
  • (!!!) Выделение, печать или сохранение произвольной области карты. Костыльное решение я делал для QLGT, но его не приняли. Там можно было распечатать только видимую часть карты.

А вот теперь каких инструментов не хватает в QMS, но есть в QLGT:

  1. Инструмент привязки карты по точкам (в визуальной форме). Не знаю, будет ли сделан, но таск завёл.
  2. Экспорт выделенного куска карты в JNX. Потребность сомнительная, но пару раз пригождалась.

Ну и ссылки:

13) (!) отмечены фичи уникальные, по сравнению с QLGT, а (-), то, что убрано, (?) - спорные изменения
14) В случае привязок Ozi, нужно открывать .map файл, в случае привязок .pgw+.prj открывать нужно одноимённую картинку
15) К сожалению, на карты и привязки с http://loadmap.net он упорно ругается

// Читинза под снегом 2

Их было четверо…
Они шли, шли, шли и, наконец, пришли!

Наконец-то первый полноценный снегоступный ПВД за сезон. То несросты, то переносы, но всё-таки собрались: Я, Коля, Кирилл и Гена.

А вообще, пробую завести ещё одну традицию: снегоступинг на Читинзу во второй половине января или начале февраля. В прошлом году была первая серия.

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

Маршрут изначально намечали:
Партизан (пл.98 км) - руч.Просечный - С-В хребет - вершина 1156 м - трверс на Читинзу - Читинза - С-З хребет - р.Постышевка - Наречное.

Но в электричке скорректировали его до:
Красноармейский - Ручьи - С-С-В хребет (классика) - Читинза - траверс на Смольную - Смольная - С-В хребет - вершина 734 м - руч.Прав.Лесопильный - Тигровой

Небольшая сводка:

День Протопали
км
Набор высоты
м
Сброс высоты
м
Время в движении
ч
Средняя скорость
км/ч
Начало движения
ч
Конец движения
ч
Сб 16.9 1434 554 06:25 2.0 10:00 18:34
Вс 14.2 201 1091 04:33 3.1 09:04 14:38
Всего 31 1635 1645 10:58 2.8


Подкатом немного текста и фотографий.

// Электродвигатели "на пальцах"

Не могу не пропиарить цикл статей по управлению и устройству различных электродвигателей (ДПТ, АД, СД, всякие шаговики и так далее):

Да и вообще рекомендую блог к подписке: НПФ ВЕКТОР

// Про снегоступы

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

  • Гуляешь по парку? Пожалуйста - walking!
  • Чуть сложнее? Да на здоровье - hikking!
  • Уже несёшь дом за спиной? Всегда рады - backpacking!
  • Идёшь в лыжный поход? Нет проблем - randonnee skiing (или ski touring)!
  • Hillwalking, mountaineering, и так далее.

Под каждую нишу своё снаряжение, подготовленные тропы, гиды и так далее.

При чём тут снегоступы? Оказывается и для них есть свои названия:

  • Наш жаргонный «снегоступинг» - это snowshoeing,
  • а «снегоступер» - snowshoer.

В статье на википедии про это есть. Уж не знаю, существуют ли подготовленные снегоступные трассы, но если ответ положительный - я не удивлюсь :)

// Как дышать на холоде

Хорошая статья на тему (автор - полярник):

Правда не знал, что -20, даже при ветре, это экстремально холодно :)

По способам: всё правильно. К примеру, дыхание ртом, когда язык загибаешь к нёбу. Про этот способ несколько лет назад сказал мой друг Олег. С тех пор и пользуюсь. Балаклава с «намордником» тоже решает. Правда скулы нужно не забывать закрывать, а то легкие не застудишь, а ряху обморозишь.

// Малый треверс Ботанического хребта и г.Острая по С-З гребню

Кто не понял - название шутка. Привет Спайдеру ;-)

На воробей сходить никого сблатовать не получилось. Пришлось ноги напрячь, хотя бы где-то в районе города. Результат:

  1. Время: 6:15
    1. в движении: 5:06
  2. Километраж: 16.2 км
  3. Средняя скорость: 3.17 км/час
  4. Общий набор высоты: 1076 м
  5. Общий сброс высоты: 939 м

К слову сказать - до Острой не дошёл, но об этом дальше.

// Обновление Qt Creator

Пока LOG, Habrahabr и другие гудят по поводу смены лицензионной политики в части Qt (переход на LPGL3) и QtC (переход с LGPL2.1 на GPL3 /именно GPL/ с исключением для плагинов), у меня дошли руки обновить PPA: https://launchpad.net/~adrozdoff/+archive/ubuntu/qtcreator-git

Ну и несколько интересных (для меня) изменений, которые стали доступны в этом билде. Добро пожаловать под кат.

// C++11: несуразность std::thread

Пост-вопрос.

Может кто объяснить, почему в стандарт вошла настолько обрезанная версия реализации std::thread? Ведь предлагаемый интерфейс не предоставляет абсолютно никаких средств передачи параметров потоку в момент создания, к примеру, тот же размер стека, что крайне актуально на всяких RTOS. При этом Boost.Thread такую возможность предоставляют средствами boost::thread::attributes:

    template <class F>
    explicit thread(attributes& attrs, F f);
 
    template <class F>
    thread(attributes& attrs, F &&f);
 
    template <class F, class ...Args>
    explicit thread(attributes& attrs, F&& f, Args&&... args);

Средства хоть и лимитированные, но доступ к native_handle атрибута позволяют тюнить параметры на конкретной платформе. Но в стандартной библиотеке нет и их. Нипанимать. Explain. Explain.

PS libstdc++ зато предоставляет достаточно простые средства, что бы добавить поддержку своих потоков (на той же RTOS), не прибегая к модификации кода библиотеки (если кому интересно, могу на пальцах разбросать как, но без полной реализации).

// C++: категории итераторов

Добротное разъяснение (кому непонятно это и это (ну и по ссылкам отсюда)) категорий итераторов на ru.SO:

// ThinkPad T530, WiFi и DEAUTH_LEAVING

После экспериментов с роутером Zyxel Keenetic 4G II (прошил неофициальную прошивку серии V1 (V1.11.RU.NDMS), на родной серии V2 непредсказуемо работал multicast IPTV) заметил, что WiFi стал работать как-то нестабильно (затыки с сайтами, постоянный реконнект у мессенджеров). Временами, но стабильно, стал вылазить диалог с просьбой ввести пароль от точки. Будто бы порвалась связь и не получилось подключиться с какого-то количества попыток.

Размышляя, что менял (ну кроме самой прошивки), вспомнил, что я переключил WiFi с режима 11b/g на режим 11b/g/n (раньше прошивка читалки не могла цепляться, если AP в таком режиме, после прошивку исправили, а настройки так и остались). Действительно, когда я переключил роутер обратно в режим 11b/g, то всё стало на свои места, так что не прошивка виновата. Казалось бы - решение найдено, но такой путь - не наш метод (хотя… если ничто другое не помогает, то лучше синица в руках, чем журавль в небе).

// OpenOCD, GDB и (сильно)удалённая отладка

Статью изначально опубликовал на Хабре: http://habrahabr.ru/post/274179/

Дано:

  1. устройство с ARM926E-JS (Cypress FX3) на борту;
  2. находится на другом континенте;
  3. подключено (JTAG+USB+COM) к Linux компу;
  4. на комп есть SSH доступ (и больше ничего, только SSH порт).

Проблема: устройство нужно отлаживать и писать под него код. И делать это, желательно, удобно.

Решение с использованием OpenOCD, GDB и Qt Creator, а так же описание пути к нему, под катом.

// г.Голец

Запоздалый пост. Краткое описалово может чуть позже (или никогда) накатаю, а фото вот:
https://picasaweb.google.com/116960244871002539190/102015

// MinGW GCC 5 в Trusty

Сделал PPA, куда положил MinGW GCC 5: https://launchpad.net/~adrozdoff/+archive/ubuntu/mingw

Версия GCC на момент написания поста: 5.3.0. Сборка зависит от репозитория https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test/+packages (если надумаете собирать сами).

Краткие характеристики сборки:

  • Модель потоков: только posix (требуется libwinpthreads), т.к. позволяет использовать все возможности C++11/C++14. Если будет спрос на win32, то нужно только добавить одну строчку и чуть подкорректировать альтернативы (т.е. сборка поддерживает, просто выключил win32).
  • Обработка исключений: sjlj для win32 и seh для win64
  • Сборка для Win32 и Win64

Добавление репозитория:

  sudo apt-add-repository ppa:adrozdoff/mingw

Установка:

  sudo apt-get install gcc-5-mingw-w64 g++-5-mingw-w64

Компилятор с суффиксом -5, что бы не конфликтовать с тем, что распространяется вместе с Ubuntu/Mint.

В этом же репозитории планирую выкладывать сборки библиотек.

// Выбор дефолтного компилятора в Ubuntu/Mint/Debian

Создать альтернативы:

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 99
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 10
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5   20
 
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 99
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 10
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5   20
 
sudo update-alternatives --install /usr/bin/cc cc /usr/bin/gcc 99
sudo update-alternatives --set cc /usr/bin/gcc
 
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++ 99
sudo update-alternatives --set c++ /usr/bin/g++

После чего можно переключаться вручную через меню:

sudo update-alternatives --config gcc
sudo update-alternatives --config g++

или скриптом:

sudo update-alternatives --set gcc /usr/bin/gcc-5
sudo update-alternatives --set g++ /usr/bin/g++-5

или вернуть в автоматический режим:

sudo update-alternatives --auto gcc
sudo update-alternatives --auto g++

Снести альтернативы:

sudo update-alternatives --remove-all gcc 
sudo update-alternatives --remove-all g++

Или только указанную:

sudo update-alternatives --remove gcc /usr/bin/gcc-4.9
sudo update-alternatives --remove g++ /usr/bin/g++-4.9

В последнем случае, подберётся другая альтернатива (на основе приоритета) и выбор будет выставлен в auto. Если альтернатив нет, то будут почищены все симлинки.

На основе: http://askubuntu.com/questions/26498/choose-gcc-and-g-version

// Про использование ссылок и указателей в C++

Данная статья практически на 100% отражает и мой подход к использованию ссылок и указателей, рекомендую к ознакомлению:
http://eao197.blogspot.ru/2015/11/progthoughts-c.html

Тезисно:

  • void f(const T &p) ожидает реально существующий объект, но не изменяет его;
  • void f(T &p) ожидает реально существующий объект и изменяет его;
  • void f(const T *p) ожидает объект или nullptr, если объект существует, то не изменяет его;
  • void f(T *p) ожидает объект или nullptr, если объект существует, то изменяет его;
  • void f(unique_ptr<T> p) ожидает объект или nullptr; если объект существует, то забирает ответственность за его удаление;
  • void f(shared_ptr<T> p) ожидает объект или nullptr; если объект существует, то разделяет владение этим объектом (что дает право функции f() сохранить p у себя для дальнейшего использования или передать кому-то еще).

// C++: inline namespace

Как-то упустил сей момент:

Вообще FAQ стоит перечитать.

// FFmpeg loop input

Если нужно сделать повторный стриминг небольшого файла (или просто сделать большой файл из нескольких повторов маленького), то поможет такая команда:

ffmpeg -re -f lavfi -i "movie=filename=/some/path/input.mp4:loop=0, setpts=N/(FRAME_RATE*TB)" -ar 44100 -f flv rtmp://some.server/app/live

Чуть подробнее:

  1. -re процессит входные фреймы так, как если бы это был live stream
  2. формат входного файла lavfi говорит, что входной файл, это не регулярный файл, устройство или сетевой ресурс, а описание графа фильтра (комплексного)
  3. соответственно аргументом -i становится описание графа фильтра:
    1. movie - фильтр задаёт источник данных, а его параметр loop=N задаёт число повторов, 0 - бесконечное число раз, отличное от нуля - будет сделано именно такое число повторов.
    2. setpts - предыдущий фильтр действует принципу KISS: попросили повторять файл - буду, но PTS будет оставаться без модификаций, соответсвенно муксеру это может (и даже, скорее всего, обязательно) показаться неприятным. Соответственно нам нужно пересчитать PTS на основе прошедших (N) кадров, фреймрейта (FRAME_RATE) и time-base входного PTS (TB, про time-base я уже писал)

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

Продублировал как ответы на вопросы на сайта Stack Exchange:

// Добавляем PGP ключ к Launchpad

Просто памятка:

  1. Генерируем ключ (gpg –gen-key).
  2. Экспортируем ключ (gpg -a –export <тут мыло или другой идентификатор ключа>, а подробнее тут: https://www.gnupg.org/gph/en/manual/x56.html).
  3. Идём на http://keyserver.ubuntu.com/ и добавляем в окно «Submitting a new OpenPGP Key» ключ экспортированный на прошлом шаге.
  4. Теперь получаем отпечаток (fingerprint) ключа (gpg –fingerprint)
  5. Идём на https://launchpad.net/~USERNAME/+editpgpkeys, проходим все круги ада шаги авторизации и на странице внизу находим «Import an OpenPGP key» и в поле ввода копируем свой отпечаток с предыдущего шага. Причём нажатие на кнопку Import Key может как-то странно реагировать, тогда как нажатие Enter в онке ввода отпечатка работает как надо.
  6. Ждём письма на почту.
  7. Расшифровываем файл из письма (gpg -d file.txt).
  8. Переходим по ссылке из файла.
  9. PROFIT.

Имеет смысл в ~/.profile или ~/.bashrc добавить строки:

# PPA
export DEBFULLNAME="Foo Bar"
export DEBEMAIL="foo_bar@gmail.com"

Одно но: полное имя и почта должны соответствовать идентификатору ключа GPG. Иначе - создавайте алиасы.

// IceWM: I'm alive!

Хороший WM16). Официально не развивается с 2013 года. Хорошей новостью является то, что автор не совсем на него забил и, хотя бы, обновляет сайт. Собственно на сайте появилась ссылка на неофициальный, но развиваемый репозиторий: https://github.com/bbidulock/icewm, так что реквесты приветствуются :)

// Перекличка

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

// О качестве документации и понимании сути

Есть такой чип: Cypress FX3. Это чип для построения USB 3.0 устройств. Внутри железная реализация протокола, 512кБ памяти и ядро ARM926E-JS. Cypress предоставляет SDK, в котором поставляется RTOS ThreadX и необходимый код для работы с их железом.

Как и классических встраеваемых SDK есть возможность ставить пользовательские колбеки и, по сути, управлять и строить логику конкретного приложения, ну и реализовать нужное вам USB 3.0 (2.0 тоже) устройство.

// FFmpeg и VP9 (libvpx)

Тут немец один в почту постучался. У него проблемы с кодированием кодеком VP9:

ffmpeg: /build/buildd/libvpx-1.3.0/vp9/encoder/vp9_encodeframe.c:1747: rd_pick_partition: Assertion `tp_orig < *tp' failed.

Если вы сидите на каком-нить Mint 17 или Ubuntu 14.04, то у вас в системе стоит libvpx версии 1.3.0 в котором есть баг: при параметре arnr-maxframes равным нулю он крешится вот таким вот образом. Причем 0 - это валидное значение согласно документации. Если эту опцию принудительно не указывать для vpxenc, то он нормально кодирует, т.е. использует какое-то значение отличное от нуля, если указать - такой же креш. А вот FFmpeg, там внутри тоже не без косяка: лапша в настройках, задаёт дефолтное значение в 0, хотя разработчики рассчитывали (судя по всему) как раз на -1. Потому такая петрушка.

Лечится указанием ffmpeg опции -arnr-maxframes со значением -1 или больше 0. -1 - включит это самое «дефолтное» значение внутри libvpx.

В новых версиях libvpx проблема исправлена. Репорты:

ЗЫ о целесообразности использования VP9 меня не спрашивайте. Меня просто спросили, а я разобрался :) ЗЗЫ FFmpeg версии 2.8.1 но роли это не играет.

// Qt Creator из Git, VirtualBox и Linux Guest

Заголовок не отражает всей сути. Конкретно:

Проблема: при запуске крешится. Выводится такой стек-трейс:

Нажмите, чтобы отобразить

Нажмите, чтобы скрыть

alexd@alexd-VirtualBox ~ $ qtcreator-git
libGL error: pci id for fd 18: 80ee:beef, driver (null)
OpenGL Warning: glFlushVertexArrayRangeNV not found in mesa table
OpenGL Warning: glVertexArrayRangeNV not found in mesa table
OpenGL Warning: glCombinerInputNV not found in mesa table
OpenGL Warning: glCombinerOutputNV not found in mesa table
OpenGL Warning: glCombinerParameterfNV not found in mesa table
OpenGL Warning: glCombinerParameterfvNV not found in mesa table
OpenGL Warning: glCombinerParameteriNV not found in mesa table
OpenGL Warning: glCombinerParameterivNV not found in mesa table
OpenGL Warning: glFinalCombinerInputNV not found in mesa table
OpenGL Warning: glGetCombinerInputParameterfvNV not found in mesa table
OpenGL Warning: glGetCombinerInputParameterivNV not found in mesa table
OpenGL Warning: glGetCombinerOutputParameterfvNV not found in mesa table
OpenGL Warning: glGetCombinerOutputParameterivNV not found in mesa table
OpenGL Warning: glGetFinalCombinerInputParameterfvNV not found in mesa table
OpenGL Warning: glGetFinalCombinerInputParameterivNV not found in mesa table
OpenGL Warning: glDeleteFencesNV not found in mesa table
OpenGL Warning: glFinishFenceNV not found in mesa table
OpenGL Warning: glGenFencesNV not found in mesa table
OpenGL Warning: glGetFenceivNV not found in mesa table
OpenGL Warning: glIsFenceNV not found in mesa table
OpenGL Warning: glSetFenceNV not found in mesa table
OpenGL Warning: glTestFenceNV not found in mesa table
libGL error: core dri or dri2 extension not found
libGL error: failed to load driver: vboxvideo
OpenGL Warning: XGetVisualInfo returned 0 visuals for 0000000001deadb0
OpenGL Warning: Retry with 0x8002 returned 0 visuals
OpenGL Warning: XGetVisualInfo returned 0 visuals for 0000000001deadb0
OpenGL Warning: Retry with 0x8002 returned 0 visuals
OpenGL Warning: glXGetFBConfigAttrib for 0000000001deadb0, failed to get XVisualInfo
OpenGL Warning: XGetVisualInfo returned 0 visuals for 0000000001deadb0
OpenGL Warning: Retry with 0x8002 returned 0 visuals
OpenGL Warning: glXGetFBConfigAttrib for 0000000001deadb0, failed to get XVisualInfo
OpenGL Warning: XGetVisualInfo returned 0 visuals for 0000000001deadb0
OpenGL Warning: Retry with 0x8002 returned 0 visuals
OpenGL Warning: glXGetFBConfigAttrib for 0000000001deadb0, failed to get XVisualInfo
OpenGL Warning: XGetVisualInfo returned 0 visuals for 0000000001deadb0
OpenGL Warning: Retry with 0x8002 returned 0 visuals
OpenGL Warning: glXGetFBConfigAttrib for 0000000001deadb0, failed to get XVisualInfo
OpenGL Warning: XGetVisualInfo returned 0 visuals for 0000000001deadb0
OpenGL Warning: Retry with 0x8002 returned 0 visuals
OpenGL Warning: glXGetFBConfigAttrib for 0000000001deadb0, failed to get XVisualInfo
OpenGL Warning: XGetVisualInfo returned 0 visuals for 0000000001deadb0
OpenGL Warning: Retry with 0x8002 returned 0 visuals
OpenGL Warning: glXGetFBConfigAttrib for 0000000001deadb0, failed to get XVisualInfo
OpenGL Warning: XGetVisualInfo returned 0 visuals for 0000000001deadb0
OpenGL Warning: Retry with 0x8002 returned 0 visuals
OpenGL Warning: glXGetFBConfigAttrib for 0000000001deadb0, failed to get XVisualInfo
OpenGL Warning: XGetVisualInfo returned 0 visuals for 0000000001deadb0
OpenGL Warning: Retry with 0x8002 returned 0 visuals
OpenGL Warning: glXGetFBConfigAttrib for 0000000001deadb0, failed to get XVisualInfo
OpenGL Warning: XGetVisualInfo returned 0 visuals for 0000000001deadb0
OpenGL Warning: Retry with 0x8002 returned 0 visuals
Could not initialize GLX
0  libLLVM-3.6.so.1           0x00007fe411df7912 llvm::sys::PrintStackTrace(_IO_FILE*) + 34
1  libLLVM-3.6.so.1           0x00007fe411df5eb1
2  libpthread.so.0            0x00007fe431190340
3  libc.so.6                  0x00007fe43085ecc9 gsignal + 57
4  libc.so.6                  0x00007fe4308620d8 abort + 328
5  libQt5Core.so.5            0x00007fe43143230e
6  libqxcb-glx-integration.so 0x00007fe4325e52dc
7  libqxcb-glx-integration.so 0x00007fe4325e60f8
8  libqxcb-glx-integration.so 0x00007fe4325e484b
9  libQt5XcbQpa.so.5          0x00007fe429bbcf91 QXcbIntegration::createPlatformOpenGLContext(QOpenGLContext*) const + 49
10 libQt5Gui.so.5             0x00007fe4303e721d QOpenGLContext::create() + 45
11 libUtils.so.1              0x00007fe43205afc5 Utils::HostOsInfo::canCreateOpenGLContext(QString*) + 165
12 libQmlDesigner.so          0x00007fe40a098f2c QmlDesigner::QmlDesignerPlugin::initialize(QStringList const&, QString*) + 28
13 libExtensionSystem.so.1    0x00007fe4323111e6 ExtensionSystem::Internal::PluginSpecPrivate::initializePlugin() + 246
14 libExtensionSystem.so.1    0x00007fe43230920c ExtensionSystem::Internal::PluginManagerPrivate::loadPlugin(ExtensionSystem::PluginSpec*, ExtensionSystem::PluginSpec::State) + 828
15 libExtensionSystem.so.1    0x00007fe43230d070 ExtensionSystem::Internal::PluginManagerPrivate::loadPlugins() + 256
16 qtcreator                  0x0000000000409a31
17 libc.so.6                  0x00007fe430849ec5 __libc_start_main + 245
18 qtcreator                  0x0000000000409db2
Аварийный останов

Существует какая-то проблема в реализации поддержки OpenGL в гостевых расширениях VirtualBox. В результате это аффектит два плагина: QmlDesigner и QmlProfiler.

В качестве work-around можно не загружать эти плагины (для меня не критично, но для кого-то может оказаться - очень, но тогда добивайтесь более действенного результата сами). Для этого сначала запустить Qt Creator так:

qtcreator-git -noload QmlDesigner -noload QmlProfiler

после чего выключить загрузку этих плагинов в настройках и запускать QtC обычным образом.

// Ускорение позиционирования в удалённом flv файле при использовании http-транспорта

Пост основан на двух вопросах на Тостере и RU.SO. На RU.SO я же накатал ответ, на основе которого и буду строить свой псто. Кроме того, рассматриваю более подробно как работает перемотка со стороны FFmpeg.

В общем, жаждущие - подкат.

// Горелка Optimus Vega

Волею судеб, китайская BRS-8 оказалась первой моей шланговой горелкой (мультитопливной тоже, но роли не играет). Но был замечен минус: после обычных накручивающихся (через ковеевский переходник Cobra) ощущался повышенный расход газа. Но плюсы контура испарителя и возможность погреть баллон очень сильно манили. Ещё хотелось чего-то более лёгкого: вес «газового» комплекта BRS-8 у меня доходит до 500 грамм, что не сильно мало.

Рассматривал различные варинты, взвешивал за и против (если кому интересно: выкладки могу опубликовать), ориентировался на известные бренды. Остановился на Optimus Vega, при покупке на eBay она встала мне с доставкой около 4000 руб, текущая цена, в районе 7000 руб, поставила бы на ней крест изначально. Собственно варианты были следующими:

  • Optimus Vega
  • MSR WindPro II
  • Primus Express Spider
  • Primus Gravity II EF

Плюс краем глаза смотрел на Fire-Maple FMS-118 (забегая вперёд, скажу, что в текущей ситуации остановился бы на ней)

Итак, сама горелка:

// Слоны идут на север 2. Или: даже корабли не выходят в море в понедельник

Вводное слово

Где-то 30 августа звонит Женя и предлагает на неделю сгонять на севера Приморья, поглядеть на Большой Амгинский, сходить на г.Курортная, посетить теплые источники и вообще, полюбоваться красотами северной Приморской природы. А я, зная эти красоты, просто не мог отказаться от такого предложения, благо жена, услышав о чём речь, сама сказала - ехать! Вот только сделала ремарку по поводу отправки в понедельник 14, а не в воскресенье 13. Но мы не суеверные!

// День программиста

С праздником, коллеги! Что бы не было в вашем коде:

#define TRUE FALSE

// Расход газа в походе

Добрая статья: http://www.mount.ru/shop/dir.php?id=235 в целом соответствует моему опыту использования газа.

Конспективно:

  1. Минимальный: 30 грамм/человек/день
    1. пожалуй только на Jet Boil и прочих интегрированных системах или котелками с радиаторами плюс использование горелки только доведения до кипения и запаривание еды. У самого такого расхода не получалось.
  2. Стандартный: 60-90 грамм/человек/день
    1. в т.ч. готовка риса, гречки, но отсутствие топления снега и льда. Вода от 7-10 градусов. Каши из перловки и кукурузы - в пролёте. Наличие ветрозащиты. Котёл 2.7 л, для горелок, Ковея, алюминиевый.
  3. Экстремальный: от 100 до 300, а то и выше грамм/человек/день
    1. топление снега, готовка на большой высоте: на берельском седле, по ощущениям, потребление было около 120 грамм.
    2. отсутсвие защитных ветровых стенок, экранов, неэффективные (костровые: с овальным дном или с нагаром, который является отличным теплоизолятором) или слишком большие котлы (больше 2-3 литров - уже много потерь, нужно озадачиться теплотканью).

Выводы:

  1. В низкогорье (до 2000-2500 м) и на равнине при отсутствии топления снега при готовке (т.е. будете не просто запаривать, а варить) можете уложиться в 60-70 грамм и меньше
  2. При топлении снега увеличьте до 90-100
  3. При увеличении высоты доведите до 120

Иногда получается комбинировать, к примеру:

  1. на Jet Boil или чём-то подобном натопить и накипятить воды и залить в термосы
  2. основное блюдо приготовить на горелке добавляя туда уже подогретую и натопленную воду

При таком раскладе, расход выше чем чисто на Jet Boil, но проще готовить на палатку из 3-4 человек плюс меньше расход, чем чисто на горелке.

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

// Qt5, OpenGL и Ubuntu/Mint

Временами, при сборке ловится такое:

/usr/bin/ld: cannot find -lGL
collect2: error: ld returned 1 exit status

При этом в системе наблюдается такое:

$ locate libGL.so
/usr/lib/i386-linux-gnu/mesa/libGL.so.1
/usr/lib/i386-linux-gnu/mesa/libGL.so.1.2.0
/usr/lib/insync/libGL.so.1
/usr/lib/nvidia-346-updates/libGL.so
/usr/lib/nvidia-346-updates/libGL.so.1
/usr/lib/nvidia-346-updates/libGL.so.346.82
/usr/lib/x86_64-linux-gnu/mesa/libGL.so
/usr/lib/x86_64-linux-gnu/mesa/libGL.so.1
/usr/lib/x86_64-linux-gnu/mesa/libGL.so.1.2.0
/usr/lib/x86_64-linux-gnu/primus/libGL.so.1
/usr/lib32/nvidia-346-updates/libGL.so
/usr/lib32/nvidia-346-updates/libGL.so.1
/usr/lib32/nvidia-346-updates/libGL.so.346.82

Т.е. вроде всё есть, но чего-то не хватает. А не хватает того, что они живут в директориях, которые не видны линковщику. Для рантайма средство есть через aternatives:

x86_64-linux-gnu_gl_conf
x86_64-linux-gnu_egl_conf

Для девелопмента должен стоять пакет libgl1-mesa-dev. После его установки станет так:

$ ls -l /usr/lib/x86_64-linux-gnu/libGL.so
lrwxrwxrwx 1 root root 13 марта 12 08:47 /usr/lib/x86_64-linux-gnu/libGL.so -> mesa/libGL.so

Проблема в том, что пакет стоит, а файла нет… Скорее всего были какие-то нюансы при обновлении или ещё чего. Лечится:

sudo apt-get install --reinstall libgl1-mesa-dev

// Обновлённый графический стек в Ubuntu/Mint

Собственно, не только стек, но и ядро 3.19

Основная ссылка: http://www.opennet.ru/opennews/art.shtml?num=42744

Команда для обновления:

sudo apt-get install --install-recommends linux-generic-lts-vivid xserver-xorg-core-lts-vivid xserver-xorg-lts-vivid xserver-xorg-video-all-lts-vivid xserver-xorg-input-all-lts-vivid libwayland-egl1-mesa-lts-vivid

Стоит отметить, что при наличии PPA xorg-edgers у вас не получится обновиться: нужно сначала вычистить этот PPA и все установленные из него пакеты заменить на дистрибутивные. Но воспользоваться для этого ppa-purge не получится: удивитесь количеству конфликтов.

Я делал вручную по следующему алгоритму…

ВНИМАНИЕ!!! СЛЕДУЙТЕ ДАННЫМ ИНСТРУКЦИЯМ ТОЛЬКО В СЛУЧАЕ, ЕСЛИ ВЫ РЕАЛЬНО ПОНИМАЕТЕ, ЧТО ДЕЛАЕТЕ. УБИТЬ СИСТЕМУ ТАК ПРОЩЕ ПРОСТОГО.

Перво-наперво: выполняйте команды из чистой консоли, а не из терминала. Если вы не понимаете о чём речь, лучше тут и остановиться.

Далее, для простоты на x86_64 системах стоит удалить i386 пакеты - они ставились, например, при установке Skype, TeamViewer или Wine. Соответсвенно, сами программы тоже снесутся. На всякий случай стоит сохранить список:

dpkg -l | grep :i386 | awk '{print $2}' > i386_list.txt

После чего нужно их удалить:

dpkg -l | grep :i386 | awk '{print $2}' | xargs sudo apt-get remove

Нет стоит использовать purge на этой стадии.

Затем нужно удалить в настройках apt репозиторий xorg-edgers и обновить список пакетов:

sudo apt-get update

После, нужно заменить все пакеты в названии которых (точнее версии) содержатся слова xedgers ,sarvatt и ricotz, а так же пакеты:

  • ppa-purge
  • wayland
  • i915

которые содержатся в данном репозитории, но не соответствует правилам вышеприведённым правилам именования, на пакеты из основного репозитория.

Сделать этом можно в два этапа. Сначала удаляем пакеты игнорируя все зависимости:

dpkg -l | grep 'xedgers\|sarvatt\|ricotz' | awk '{print $2}' | xargs sudo dpkg -r --force-depends ppa-purge wayland i915

Затем восстановить поломанные зависимости:

sudo apt-get install -f

Поставятся уже дистрибутивные пакеты.

После этого можно восстановить i386 пакеты и доставить пакеты ppa-purge, i915, если необходимо.

После данных действий, можно будет обновить стек xorg.

// C++11: std::error_code & std::error_condition в GCC 4.8/4.9 и 5.1

Кусок кода:

    auto ecod = make_error_code(std::errc::resource_unavailable_try_again);
    auto econ = make_error_condition(std::errc::resource_unavailable_try_again);
    assert(ecod == econ);

Согласно документации ассерт не должен срабатывать. Компилятор GCC 4.8 и 4.9 в Linux Mint собирает код и выдаёт такое при запуске:

$ ./webserver
webserver: webserver.cpp:661: int main(int, char**): Assertion `ecod == econ' failed.
Aborted

Внезапно.

GCC 5.1 собирает и нормально обрабатывает ситуацию.

// Переключение входов в UAC

В спеке USB Audio Class есть описание чудного компонента - «Selector Unit (SU)», который позволяет переключать несколько входов на один выход. Терминах USB спецификации: несколько Input Terminals (IT) к одному Output Terminal (OT). Сразу отмечу, что к каждому юниту может быть прикреплён строковый дескриптор, который его описывает. Если такое поведение не нужно, то ставится ноль и используется имя соответствующей USB функции (UAC в нашем случае) или устройства как такового, если дескриптор для функции тоже не задан, в общем - иерархия.

Но самый смак, как он обслуживается в разных операционных системах. Рассмотрим триаду: Windows (конкретно Win8), Linux (Ubuntu 14.04), MacOSX (TBD).

Windows

У вас 16 входов, между которыми нужно переключаться без потери стрима? Получите 16 отдельных устройств для записи с одинаковыми именами к которым система сама добавит #1, #2 и так далее, начиная со второго! Основой для имени будет выбран тип терминала (Микрофон, к примеру) и имя функции (ну или устройства)! Причём переключаться можно путём выбора дефолтного устройства для записи. Остальные устройства помечаются при этом как временно недоступные. Windows лучше знает, что показывать пользователю: вдруг производитель железки какую каку в имени написал!

UAA появилась ещё в XP, а воз почти и не тронулся. Прекрасный UI.

Linux

Стандартный контрол звука в Юнити входы не увидел. Но показал честно одно устройство. Откуда будет идти звук - гадай (привет pulseaudio!). GNOME Alsa Mixer - вообще какую-то муть вывел. А вот консольный alsamixer, правильно отобразил карту, а при выборе её - селектор для входов. При этом корректно отобразились строковые описания входов. Как обычно для Linux: UI отстрой, консоль рулит!

Возможно - это кривые настройки у убунты. Сегодня проверю на Mint. Но универсальный и самый дружественный способ один: выбрать в alsamixer.

Mac OS X

Версию уточню. Сам не любитель маков. НО! Это единственная система в которой это сделано для человеков: устройство отображается одно, к нему подписывается сколько у него есть входов и выходов и даётся возможность выбрать вход, если он переключается через Selector Unit. Блеск.

Завтра уточню по поводу имён, но, вроде как, аналогично alsamixer, отображает корректно.

Послесловие

А не будет его. Сами выводы делайте. Лучше ссылок чуток накидаю:

// AvCpp: API-2 rework, веха вторая

Продолжаем отслеживать судьбу изменений, описанных в AvCpp: API-2 rework, веха первая.

Как обычно, объём работ отличается от того, что было запланировано. Итак, что сделано:

  1. Работа со словарями и поддержка оных во всех местах, где только можно. Это вызвало необходимость разнести открытие входного потока и поиск информации о стриме (Снова FFmpeg и low-latency). Как следствие, добавился новый вызов: av::FormatContext::findStreamInfo(). Он может принимать коллекцию словарей для каждого стрима в потоке.
  2. Начата работа над фильтрами. Уже появилась базовая инфраструктура. Но пока нет понимания в каком виде оно должно получиться на выходе.
  3. В рамках чистки кода тотально переработана обработка ошибок. Теперь это делается через std::error_code, который передаётся опциональным аргументом в те функции фейл которых может приводить к неоднозначностям в будущем. Если переменная для кода ошибки не передана, будет выброшено исключение av::Exception которое будет содержать данный код. Планируется, что набор исключений расширится под каждую сущность. Данные изменений повлекли достаточно сильные изменений в API, требующие изменений в коде приложений, которые их используют. При обработке ошибок стоит учитывать категорию оных. На дынный момент используется, как минимум три:
    • avcpp_category() - для внутренних ошибок AvCpp
    • ffmpeg_category() - для ошибок, пришедших от FFmpeg
    • system_category() - для системных ошибок, в основном так рапортуются ошибки выделения памяти при помощи встроенных av_alloc() (когда владение принимается FFmpeg'ом и он сам освобождает, как следствие, использовать new/new[] нет возможности). Целесообразность использовать std::bad_alloc обдумывается.

Ну и главное, реорганизация бранчей:

  • все наработки первой вехи выделены в отдельный бранч api-2.0 (исправляются только ошибки)
  • старый мастер стал бранчем api-legacy (для совместимости, самостоятельно тут ничего не исправляется, только принимаются мерж-реквесты)
  • вся разработка перемещена на бранч master

Что осталось:

  1. Интерфейс опций
  2. Доделать фильтры
  3. Ревизия и чистка кода в т.ч. примеров.

Планируется, что это будет сделано в следующей, третье вехе.

Как обычно, за отзывы, багрепорты и пул-реквесты буду благодарен.

// Снова FFmpeg и low-latency

В дополнение к моей прошлой заметке: x264 low latency пару статей на эту же тему, но без привязки к x264:

Стоит отметить, что в первой статье наихудшие показатели показала avformat_find_stream_info(), эта же функция не понравилась коллеге на работе, но без неё могут быть такие артефакты:

В общем, согласно документации:

The above code attempts to allocate an AVFormatContext, open the specified file (autodetecting the format) and read the header, exporting the information stored there into s. Some formats do not have a header or do not store enough information there, so it is recommended that you call the avformat_find_stream_info() function which tries to read and decode a few frames to find missing information.

Суть: просто открыть файл не всегда достаточно, что бы делать предположения о некоторых параметрах файла. Походу, с этим нужно просто смириться или попытаться предпринять меры из ссылки 1, а именно зарезать параметры probesize и analyzeduration в 32 (минимально допустимое значение).