Последнее обновление:
September 22, 2016

Есть мысль... Жми, напиши!
Что имеем: Постов : 159 Авторов: 1 Категорий: 37

Сервер-ретранслятор для IP H264 камер.

Приветствую!

В одном проекте возникла необходимость получать видео с IP камеры, вещающей в H264 формате и всё было хорошо, пока клиентов, подключённых к камере, было раз-два да обчёлся.

Но пользователей проекта становилось всё больше и камера просто не выдерживала по 5-6 клиентов и начинала адцки лагать т.к. сеть у неё всего 100 мб, да и производительность около нуля.

Было решено найти софт сервера-ретранслятора, т.к. канал от сервера до клиентов достаточно толстый, а большую часть времени он просто курит бамбук,

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

Чтож, пришлось написать свой велосипед.

Ссылочка на ГитХаб.

Написан на Qt 5.6 без использования сторонних библиотек и других зависимостей.

 

Из плюшек:

  • многопоточность (которая, сука, выжирает всё, что может: по потоку на канал камеры и по потоку на клиента),
  • независимость от сторонних библиотек (просто лень искать было подходящие 😀 )
  • говнокодность (писался на скорую руку, архитектура кастовалась походу раскуривания протоколов RTSP, RTP, SDP )
  • после сборки доработать напильником ( тестировал только на камерах проекта (китайских no-name) и собственных клиентах )
  • выкладываю  как есть  и обновляться будет лишь при возникновении багов в основном проекте т.к. всем — не угодишь и смотри предыдущий пункт =)

 

 

 

Views :

13

Qt настраиваем логирование в проекте (формат лога)

Приветствую!

Отладочные сообщения в QtCreator достаточно не информативные, особенно в большом проекте, а каждый раз прописывать  что-то вроде:

qDebug()<<"MyClass::functionName params"<<p1<<p2;

что бы знать в каком хоть классе и функции идёт вывод достаточно долго.

Мало кто знает, но можно перехватить вывод qDebug, а заодно qInfo, qWarning и т.д. делается это так:

в main.cpp  сразу после QApplication app(…); прописываем:

 qInstallMessageHandler(myMessageHandler);

В *.pro файле добавляем:

DEFINES += QT_MESSAGELOGCONTEXT

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

#include <QDateTime>
void myMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &msg)
{
    QString txt;   
    static long long uid=0; //-- номеруем вывод
    //-- название функции с классом, берём только класс и саму функцию
    QRegExp rx("([\\w-]+::[\\w-]+)");
    if (rx.indexIn(context.function) ==-1) return;
    QString function = rx.cap(1);

    QString msgSep = (msg.length()>0)? ">> " : "";

    switch (type) {
        case QtInfoMsg:
            txt = QString("Info: %1%2%3").arg(function).arg(msgSep).arg(msg);
        break;
        case QtDebugMsg:
            txt = QString("Debug: %1%2%3").arg(function).arg(msgSep).arg(msg);
            break;
        case QtWarningMsg:
            txt = QString("Warning: %1%2%3").arg(function).arg(msgSep).arg(msg);
        break;
        case QtCriticalMsg:
            txt = QString("Critical: %1%2%3").arg(function).arg(msgSep).arg(msg);
        break;
        case QtFatalMsg:
            txt = QString("Fatal: %1%2%3").arg(function).arg(msgSep).arg(msg);
            abort();
        break;
    }

    QDateTime dateTime = QDateTime::currentDateTime();
    uid++;
    txt=QString("%1:%2 %3").arg(dateTime.toString(Qt::ISODate)).arg(uid).arg(txt);

    QFile outFile(QString("%1/log-%2.log").arg(".").arg(QDate::currentDate().toString("dd.MM.yy")));
    outFile.open(QIODevice::WriteOnly | QIODevice::Append);
    QTextStream ts(&outFile);
    ts << txt << endl;
    outFile.close();


}

Дальше, если у вас Линь, то достаточно просто в консольке прописать:

tail -f  log-18.09.16.log

и весь вывод будет идти в реал тайме.

Вот как-то так =)

 

 

 

 

Views :

3

Хоткеи на клавиши мыши

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

Устанавливаем xbindkeys для отлова событий и запуска нужных комманд, а что бы вместо запуска комманд мы эмулировали нажатие клавиш установим ещё и xautomation

 

sudo apt-get install xbindkeys
sudo apt-get install xautomation

сразу создаём дефолтный конфиг файл в домашней папке:

xbindkeys -d > ~/.xbindkeysrc

Нам бы теперь нужно узнать наименование кнопок мыши, запускаем:

xev | grep state

жмём кнопки в открывшемся окне, в консоли смотрим название клавиши, а для мышки смотрим номер кнопки (Button 8, Button 9 и тд)

Правим конфиг:

sudo nano ~/.xbindkeysrc

прописываем:

#ENTER
"xte 'key Return'"
b:9

#ESCAPE
"xte 'key Escape'"
b:8

Думаю, смысл понятен?

Возможно xbindkeys уже был запущен и тогда возможны ошибки. Прибьём навсякий случай и запустим вновь:

sudo killall xbindkeys
xbindkeys

наслаждаемся =)

 

Views :

8

Установка Zend Framework 2 в Ubuntu

Тут впринципе всё просто

wget https://packages.zendframework.com/releases/ZendFramework-2.4.9/ZendFramework-2.4.9.tgz
tar -xvzf ZendFramework-2.4.9.tgz

Что бы скрипты имели доступ, нужно в конфиге серва NGINX у location php прописать

fastcgi_param ZF2_PATH /usr/lib/php/zf2/ZendFramework-2.4.9/library;

Вот как то так =)

 

Views :

20

Android MySql (QMysql) драйвер для Qt5.6 на Windows и Linux компиляция

В общем понадобилось портировать одну прогу под Андроид arm7, но она плотненько работает с базой данных, а так как я человек впринципе ленивый, то обёртку для REST API сервера было лень писать, решился на компилирование MySQL плагина, но если бы я знал тогда, что это займёт у меня 20 часов…
красноглазик

 

В общем вот вам готовый рецепт из 12 шагов для компиляции на Ubuntu и на Windows
То, что помечено windows16 -выполнять только на винде.
Установим инструменты:
1. Качаем и устанавливаем CMake https://cmake.org/download/ у меня 3.5.2
2. Разумеется Android NDK у вас уже должен быть установлен, но вдруг: https://developer.android.com/tools/sdk/ndk/index.html
windows163. Качаем и ставим MSYS https://sourceforge.net/projects/mingw/files/latest/download?source=files (отмечаем всё, что можно)
4. При установке Qt нужно было поставить и исходники (папка qt/5.6/src/qtbase), если нет её, то качаем и ставим
windows165. Открываем консольку MSYS (c:\mingw\msys\1.0\msys.bat), в дальнейшем все действия будут вестись в ней и для удобства выкачивания установим wget:

/c/mingw/bin/mingw-get install msys-wget-bin

1. Создадим отдельную директорию, где будем развлекаться и перейдём в неё:

mkdir /d/Projects/AndroidMySQL
 cd /d/Projects/AndroidMySQL

2. Выкачиваем саму MariaDB, а именно коннектор

wget https://downloads.mariadb.org/interstitial/connector-c-3.0.0/mariadb-connector-c-3.0.0-alpha-src.tar.gz
 tar -xzvf mariadb-connector-c-3.0.0-alpha-src.tar.gz

3. Выкачиваем и распаковываем исходники iconv http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz

wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz
 tar -xvzf libiconv-1.14.tar.gz

4. Выкачиваем и распаковываем OpenSSL

wget -c http://www.openssl.org/source/openssl-1.0.1h.tar.gz --no-check-certificate
 tar -xvzf openssl-1.0.1h.tar.gz

5. Задаём общие глобальные переменные
windows16

 export PATH="$PATH:/c/mingw/bin:/c/Program Files (x86)/CMake/bin"
 export ANDROID_NDK_ROOT=/d/Android/android-ndk-r10e
 export SR="$ANDROID_NDK_ROOT"/platforms/android-19/arch-arm/usr # Укажите платформу, под которую собираете ваши проекты (Лучше, 19)
 export BR="$ANDROID_NDK_ROOT"/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-
 export CPP="$BR"cpp
 export AR="$BR"ar
 export STRIP="$BR"strip
 export RANLIB="$BR"ranlib
 export LINKER="$BR"ld
 export OBJDUMP="$BR"objdump
 export CC="$BR"gcc
 export CFLAGS="--sysroot=$SR"
 export CPPFLAGS="$CFLAGS"
 export C_INCLUDE_PATH=$SR/include
 export ANDROID_DEV=$SR/usr
 export MAKEDEPPROG="$CC -M"

6. Собираем сначала iconv

cd libiconv-1.14
 ./configure --host=arm --prefix=$SR/usr --with-sysroot=$SR
 make
 make install

7. Собираем OpenSSL

cd ../openssl-1.0.1h
 CC="$CC -march=armv7-a -mfloat-abi=softfp"
 ./Configure android-armv7 --prefix=$SR/usr no-asm
 make
 make install
 make install_sw

Если заматериться error: undefined reference to ‘__ctype_get_mb_cur_max’,
то в файл libcharset/lib/localcharset.c после дефайнов добавляем

size_t __ctype_get_mb_cur_max(void){
 return 1;
 }

8. Нус, начинаем подготовку к сборке MariaDB

В файл include/my_global.h необходимо добавить определение типа ushort

#ifndef ushort
 #define ushort uint16
 #endif

9. Подготавливаем сборку

cd ../mariadb-connector-c-3.0.0-alpha-src
mkdir build
 cd build
cmake -G "Unix Makefiles"
 -DCMAKE_BUILD_TYPE=Release \
 -DCMAKE_AR="$BR"ar.exe \
 -DCMAKE_C_COMPILER="$BR"gcc.exe \
 -DCMAKE_C_FLAGS=--sysroot=$SR \
 -DCMAKE_LINKER="$BR"ld.exe \
 -DCMAKE_RANLIB="$BR"ranlib.exe \
 -DCMAKE_STRIP="$BR"strip.exe \
 -DCMAKE_SYSTEM_NAME=Linux \
 -DICONV_INCLUDE_DIR="$SR/usr/include" \
 -DICONV_LIBRARIES="$SR/usr/lib/libiconv.a" \
 -DOPENSSL_ROOT_DIR="$SR/usr/lib/" \
 ../

10. Зажмуриваемся и собираем

make


windows16 ага, фиг то там, failed to create symbolic link ‘libmysqlclient.a’: No error
внезапно… тут, похоже, баг самого CMake, поэтому в файле
\AndroidMySQL\mariadb-connector-c-3.0.0-alpha-src\build\libmariadb\CMakeFiles\SYM_libmysqlclient.a.dir\build.make
находим строки (их по две) c -E create_symlink libmariadbclient.a libmysqlclient.a, удаляем её полностью
а так же -E create_symlink libmariadb.so libmysqlclient_r.so аналогично
и вручную копируем и продолжаем сборку

cp libmariadb/libmariadbclient.a libmariadb/libmysqlclient.a
 cp libmariadb/libmariadbclient.a libmariadb/libmysqlclient_r.a
 cp libmariadb/libmariadb.so libmariadb/libmysqlclient.so
 cp libmariadb/libmariadb.so libmariadb/libmysqlclient_r.so
 make



и ещё раз фиг error: unknown type name ‘pthread_mutex_t’
в файле ../unittest/libmariadb/thread.c
находим pthread_t threads[THREAD_NUM]; заменяем на void * threads[THREAD_NUM];
и там же заменяем pthread_mutex_t LOCK_test; на void * LOCK_test;
и опять
make

На этот раз должно всё ок пройти, ну и устанавливаем и копируем к нашему ndk

make install
mkdir "$SR/usr/lib/mariadb"
 mkdir "$SR/usr/include/mariadb/"
 cp libmariadb/*.{a,so} "$SR/usr/lib/mariadb/"
 cp ../include/* "$SR/usr/include/mariadb/"

11. Собираем плагин QMySQL, открываем обычную консольку пути только на свои замените

cd /d/Qt/5.6/Src/qtbase/src/plugins/sqldrivers/mysql/
 /d/Qt/5.6/android_armv7/bin/qmake.exe \
 "INCLUDEPATH+=$SR/usr/include/mariadb" \
 "LIBS+=-L$SR/usr/lib/mariadb -lmariadbclient -lssl -lcrypto -liconv" \
 -o Makefile mysql.pro
make
 make install

12. Разрабатываем тестовый проект
Так как зависит от libmariadb.so, то его необходимо таскать с проектом, для этого в *.pro файле проекта добавить

contains(ANDROID_TARGET_ARCH,armeabi-v7a) {
 ANDROID_EXTRA_LIBS = \
 d:/Projects/AndroidMySQL/mariadb-connector-c-3.0.0-alpha-src/build/libmariadb/libmariadb.so
 }

Пересобираем проект, запускаем, и хуй то там =)
QMYSQL driver not loaded
яоминь
Посмотрим зависимости libqsqlmysql.so, которая в каталоге /home/pavelk/Qt/5.6/android_armv7/plugins/sqldrivers

ldd libqsqlmysql.so

и опять облом, нужна ldd для arm, ладно и с этим разберёмся, например так, тынц.

ldd-avr libqsqlmysql.so

Дело в том, что в зависимостях у libmysql.so есть libmariadb.so.3, а не libmariadb.so
почуяли разницу? =))

В общем, что бы побыстроляну пофиксить
в файле libmariadb/CMakeLists.txt
находим

SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR})

и заменяем на

SOVERSION "so")

ну а дальше удалить полностью build и заново, начиная с 9 шага
troll

!пересобираем! проект, не забыть исправить в pro файле на libmariadb.so.so запускаем и радуемся =)

Итого: сэкономлено куча времени и нервов. Хоть спасибо скажите =))

Views :

152

ldd на Андроид

После портирования проги на девайс, прога в упор не хотела видеть одну из библиотек, решил глянуть через ldd, что же ей надо, но ldd на Андроиде не оказалось =(, а просто ldd её не воспринимает.

Чтож, будем делать аналог ldd но для arm =)

Вот так:

echo 'readelf -d $1 | grep "\(NEEDED\)" | sed -r "s/.*\[(.*)\]/\1/"' | sudo tee -a /usr/local/bin/ldd-arm
sudo chmod +x /usr/local/bin/ldd-arm

Потом просто

ldd-arm mylib.so

и увидим список либ, от которых зависит наша.

Ну или через стандартную утилиту ndk-depends:

/home/pavelk/Android/android-ndk-r10e/ndk-depends mylib.so

 

Вот как-то так =)

Views :

59

OpenCV warpPerspective, warpAffine без обрезки (whole image) и размер результата (destination result image size)

В общем потребовалось восстановить перспективу картинки,
на примере этой:

sheet

Как обычно — нашли 4 точки на картинке, в данном случае — углы листа, по часовой стрелке, начиная с верхнего левого:

[20, 340]
[860,110]
[1160, 650]
[200, 950]

Хотим, что бы лист располагался прямо, а для этого мы знаем, что ширина и высота листа 870 на 620 пикселей, аналогично координаты по часовой стрелке, начиная с верхнего левого:

[0, 0]
[870, 0]
[870, 620]
[0, 620]

в данном случае левый верхний угол располагается в нуле (где ещё то), а правый нижний строго по горизонтали и вертикали (мы ведь хотим расположить прямо)

ладно, пора покодить (доки нам в помощь):

/*
* Пока что всё как обычно
* открываем картинку,
* задаём найденные и целевые точки,
*/
Mat input;
input = imread("/home/pavelk/Projects/OpenCVwrapPerspective/sheet.jpg");

Point2f inputQuad[4];
inputQuad[0] = Point2f( 20, 340 );
inputQuad[1] = Point2f( 860,110 );
inputQuad[2] = Point2f( 1160, 650 );
inputQuad[3] = Point2f( 200, 950 );

Point2f outputQuad[4];
outputQuad[0] = Point2f( 0, 0 );
outputQuad[1] = Point2f( 870, 0 );
outputQuad[2] = Point2f( 870, 620 );
outputQuad[3] = Point2f( 0, 620 );

/*
* Находим матрицу трансформации
*/
Mat M = getPerspectiveTransform( inputQuad, outputQuad );

/*
* Теперь применяем трансформацию на картинке с помощью warpPerspective
*/

Mat output;
warpPerspective(input, output, M, Size(2000, 2000));

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

Посмотрим на вывод:

output1

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

Почему так происходит?

Потому, что когда мы задали целевую точку верхнего левого угла [0, 0], то при трансформации получается (см. формулу warpPerspective), что нужно взять позицию с отрицательными координатами с картинки оригинала, а откуда на ней взяться отрицательному-то значению…  Вот и получается обрезка.  Можно, конечно, заранее подгадать смещение целевых точек, что бы не было отрицательных позиций, но мы не знаем, как может повернуться исходная картинка, да и проблему с размером результата мы не решим да и вообще гадать — не мой метод.

Что будем делать?

Как следует из написанного выше — нам нужно сместить целевые точки, поэтому будем выяснять насколько их смещать, а для этого нам нужно выяснить, где окажется левый верхний угол после трансформации. Но! Не забываем, что исходная картинка может быть как угодно повёрнута, и левый нижний окажется дальше в минусе, чем верхний левый. Поэтому выясняем положение после трансформации всех четырёх углов исходной картинки, а что бы не геммороиться с определением где какой угол — найдём их ограничительную рамку, благо для этого в OpenCV есть метод boundingRect и сместим целевые точки в обратную сторону от её позиции, а бонусом по её размеру мы знаем размер итоговой картинки=)

Покодим:

/**
* Выясняем положение углов исходной картинке,
* по ширине и высоте
*/
vector<Point2f> inputCorners(4);
inputCorners[0]=Point2f(0, 0);
inputCorners[1]=Point2f(input.cols, 0);
inputCorners[2]=Point2f(0, input.rows);
inputCorners[3]=Point2f(input.cols, input.rows);

/*
* Выясняем, где они будут - применяем трансформацию
*/
vector<Point2f> outputCorners(4);
perspectiveTransform(inputCorners, outputCorners, M);

/*
* Находим ограничительную рамку
*/
Rect br= boundingRect(outputCorners);

/*
* Сдвигаем все целевые точки в противоположное направление, 
* от того, куда ушла ограничительная рамка
*/
for(int i=0; i<4; i++) {
   outputQuad[i]+=Point2f(-br.x,-br.y);
}

/*
* Ну и заново вычисляем матрицу трансформацию
* с новыми целевыми точками
*/
 M = getPerspectiveTransform( inputQuad, outputQuad );

/*
* Применяем трансформацию к картинке
* размер - как ограничительная рамка
*/
warpPerspective(input, output, M, br.size());

/*
* Ну и показываем итоговую картинку
*/
imshow("Output2", output);

Посмотрим на результат:
output2

По-моему, получилось идеально? =)

Ок, полный листинг на Qt 5.6 console application:

#include <QApplication>
#include <QDebug>
#include <iostream>

#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>

using namespace std;
using namespace cv;


int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
 
    Mat input = imread("/home/pavelk/Projects/OpenCVwrapPerspective/sheet.jpg");

    Point2f inputQuad[4];
    inputQuad[0] = Point2f( 20, 340 );
    inputQuad[1] = Point2f( 860,110 );
    inputQuad[2] = Point2f( 1160, 650 );
    inputQuad[3] = Point2f( 200, 950 );

    Point2f outputQuad[4];
    outputQuad[0] = Point2f( 0, 0 );
    outputQuad[1] = Point2f( 870, 0 );
    outputQuad[2] = Point2f( 870, 620 );
    outputQuad[3] = Point2f( 0, 620 );

    Mat M = getPerspectiveTransform( inputQuad, outputQuad );

    vector<Point2f> inputCorners(4);
    inputCorners[0]=Point2f(0, 0);
    inputCorners[1]=Point2f(input.cols, 0);
    inputCorners[2]=Point2f(0, input.rows);
    inputCorners[3]=Point2f(input.cols, input.rows);

    vector<Point2f> outputCorners(4);
    perspectiveTransform(inputCorners, outputCorners, M);

    Rect br= boundingRect(outputCorners);

    for(int i=0; i<4; i++) {
        outputQuad[i]+=Point2f(-br.x,-br.y);
    }

    M = getPerspectiveTransform( inputQuad, outputQuad );

    warpPerspective(input, output, M, br.size());

    resize(input, input, Size(1000,1000));
    imshow("Input", input);
    resize(output, output, Size(1000,1000));
    imshow("Output2", output);

    waitKey(5000);

    return app.exec();
}

Вот как-то так =)

Views :

80

Установка, настройка и пример использования gitolite

Потребовалось организовать свой git-сервер с простым распределением прав доступа и управлением.
Выбор пал на gitolite, как наиболее популярного и, как оказалось, вполне удобного.
В общем, погнали ставить:

На сервере:
устанавливаем сам git

sudo apt-get install git

Добавляем пользователя git, через которого будет работать gitolite и установим ему пароль

sudo useradd -d /home/git/ -m git
sudo passwd git

Теперь нам надо добавить git юзверя к доверенным у ssh и скажем, где искать файлы авторизации, правим /etc/ssh/sshd_config  добавляем к ВНИМАНИЕ! Если у вас вообще нет AllowUsers то добавлять её не нужно.

AllowUsers git
AuthorizedKeysFile %h/.ssh/authorized_keys

У Админа:

Генерируем свой ssh-rsa ключ и добавляем к себе же (если до этого не генерировали и не пользовались им) :

ssh-keygen
ssh-add

копируем свой публичный ключ
публичный ключ обычно лежит тут:
~/.ssh/id_rsa.pub
в папку к нашему пользователю git на сервер
/home/git/USERNAME.pub
USERNAME — ваш логин, под которым вас будет знать Гитолайт (не обязательно как ваш системный логин)
у меня это admin.pub

По быстроляну скопировать на сервер можно так:

scp ~/.ssh/id_rsa.pub user@host:/home/git/admin.pub

где user и host замените на свой для доступа по ssh к серверу

На сервере:
устанавливаем Gitolite

su - git
mkdir -p ~/bin
git clone git://github.com/sitaramc/gitolite
gitolite/install -ln ~/bin
./bin/gitolite setup -pk admin.pub
exit

установка завершена, теперь настройка.

У Админа:
все настройки осуществляются через репозиторий gitolite-admin, для этого его необходимо сначала склонировать его с сервера

cd ~
git clone ssh://git@server/gitolite-admin
cd gitolite-admin

теперь в папке gitolite-admin
в ней папка conf а в ней gitolite.conf — настройки репозиториев и прав доступа
добавим по аналогии свой репозиторий:
repo testrep
и установим права на чтение/запись пользователям admin (как и имя публичного ключа)
RW+= admin
в папке keydir хранятся публичные ключи пользователей в формате username.pub
например pavelk.pub (см далее для добавления)

применение настроек происходит обычным образом через git
в каталоге, в котором что-либо меняли:

git add .
git commit -a -m "комментарии изменений"
git push

Настройки впринципе закончены.

С клиента-разработчика

теперь для доступа к репозиторию нам необходимо поделиться с сервером своим публичным ssh ключом
для этого генерируем его у себя и сразу добавляем к себе же:
ssh-keygen
ssh-add

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

На админе обновляем настройки как уже делали выше.

cd /gitolite-admin
git add .
git commit -a -m "new user added"
git push

теперь на клиенте можем обычным образом склонировать наш репозиторий:

git clone git@server:testrep

Надеюсь, всё прошло гладко =)

Для винды:
ssh ключ можно сгенерировать с помощью PUTTYgen, сохранив публичный (id_rsa.pub) и приватный ключ (mykey.ppk),
Установим сам git git для винды
дальше в папке .ssh своего пользователя (/users/username/.ssh/ — windows 7) создаём файл id_rsa.pub
и в него копируем вывод PUTTYgen (KEY)
не забудьте выставить права на репозитории в gitolite.conf и закоммитить изменения.

Небольшой пример использования своего сервера с git:
Допустим у вас есть некий проект в папке ~/testrep
создаём локальный репозиторий:

cd ~/testrep
git init
git add .
git commit -m "коммент"

добавим наш сервер как внешний:

git remote add origin git@host:testrep

origin — просто заголовок для этого сервера testrep — имя проекта, которое задавали в conf
так как проект не содержит ничего, зададим явно ветку:

git push --set-upstream origin master

origin — имя сервера из предыдущей команды master — имя ветки
ну и выгружаем на сервер:

git push

На этом всё =)

Views :

64

QtWebEngine -зависимости или не отображается при запуске скомпилированного бинарника из операционки.

Решил тут хелп для очередной проги запилить в формате html, так как удобнее создавать.

Ну и для отображения был выбран QtWebEngine, написал простейший примерчик:

(Кому нужно просто решить проблему — в самый конец)

*.pro

QT += webengine

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtWebEngine>
#include <QDebug>

int main(int argc, char *argv[])
{
    qDebug()<<"MAIN";
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;    
    QtWebEngine::initialize(); //-- обязательно, иначе крэш!
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    return app.exec();
}

main.qml

import QtQuick 2.4
import QtQuick.Window 2.2
import QtWebEngine 1.1
Window {
    visible: true

    Rectangle {
        anchors.fill: parent
        color:"red"
    }

    WebEngineView {
          visible: true
          id: webview
          url: "http://pavelk.ru"
          anchors.fill: parent
      }
}

Компилирую, запускаю, всё ок.

webengine-loaded

Но при попытке запустить скомпилированный бинарник просто из операционки, а не из QtCreator, вижу пустое окно О_о

webengine-noloaded

Внезапно…  Думал, раз сам пример запускается, значит и WebEngine должен, а так как фон остался красным, значит WebEngine полностью не прогрузился.

Смотрел уже и через ldd webengine , в выводе все библиотеки присутствуют.

Значит, WebEngine сам ещё что-то грузит.

Оказалось, так и есть и виновник нашёлся в папке с Qt по пути Qt/5.6/gcc_64/libexec с названием QtWebEngineProcess, но самое странное, через ldd ему то же всё хватало…

Видимо, подгружает позже…

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


В общем решение оказалось простым:
export LD_LIBRARY_PATH=/home/pavelk/Qt/5.6/gcc_64/lib:${LD_LIBRARY_PATH}
путь до Qt только на свой замените, и что бы изменения вступили в силу необходимо перелогиниться.
В дальнейшем, что бы переносить прогу с QtWebEngine в qt.conf необходимо указать папку для libexec и в неё кинуть из Qt/5.6/gcc_64/libexec экзешник QtWebEngineProcess,
ну и разумеется установить lib со всеми webengine* модулями.

Вот как-то так =)

 

Views :

198

Android Автозапуск планшета/телефона при подключении зарядки/питания

Когда хочется использовать Андроид планшет как car-pc, или панель управления для станка, или просто как фоторамку, необходимо что бы он автоматически включался при подачи питания / зарядки.

Делается это просто:

    1. Рутуем девайс.
    2. Качаем root browser или total commander.
    3. Переходим в корневой каталог, ищем файл init.rc открываем на редактирование
    4. Находим в нём такую строчку:  «on charger«, а ниже будет команда, которая будет выполняться при подключении зарядки.
      По умолчанию, это «class_start charger«
    5. Заменяем эту строчку на такую:  «class_start autoOn«
    6. В каталоге «/system/bin/« создаём файлик  «autoOn» и прописываем в нём:
      #!/system/bin/sh
      su
      /system/bin/reboot
    7. Сохраняем, и изменяем права на 0755
    8. Выключаем девайс, подключаем зарядку. Через пару секунд начнётся запуск =)

Вот впринципе и всё =)

 

Views :

642