v3.3.t2
-pixel sizes for video and thumbnails are now configurable -the amount of recording and snapshot threads are now configurable -changed the default buffer and recording directories to drop the application name and also drop a level -service files are now stored in a dedicated dir -fixed logging so it will capture errors better -moved folder structure building to rdConfig() and added more error capturing -recording fps is now configurable
This commit is contained in:
parent
41ccf1d1e7
commit
83080cfe41
|
@ -1,7 +1,9 @@
|
|||
#!/bin/sh
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
if ! command -v magick &> /dev/null
|
||||
magick -version &> /dev/null
|
||||
|
||||
if [ ! $? -eq 0 ]
|
||||
then
|
||||
apt install -y git
|
||||
git clone https://github.com/ImageMagick/ImageMagick.git .build-imagemagick
|
||||
|
|
17
install.sh
17
install.sh
|
@ -7,20 +7,20 @@ if [ ! -d "/opt/mow" ]; then
|
|||
mkdir /opt/mow
|
||||
fi
|
||||
|
||||
if [ ! -d "/var/opt/mow" ]; then
|
||||
mkdir /var/opt/mow
|
||||
if [ ! -d "/var/footage" ]; then
|
||||
mkdir /var/footage
|
||||
fi
|
||||
|
||||
if [ ! -d "/etc/mow" ]; then
|
||||
mkdir /etc/mow
|
||||
fi
|
||||
|
||||
if [ ! -d "/var/opt/mow/buf" ]; then
|
||||
mkdir /var/opt/mow/buf
|
||||
if [ ! -d "/var/buffer" ]; then
|
||||
mkdir /var/buffer
|
||||
fi
|
||||
|
||||
if [ ! -d "/var/opt/mow/rec" ]; then
|
||||
mkdir /var/opt/mow/rec
|
||||
if [ ! -d "/var/mow_serv" ]; then
|
||||
mkdir /var/mow_serv
|
||||
fi
|
||||
|
||||
cp -v ./.build-mow/mow /opt/mow/bin
|
||||
|
@ -36,12 +36,13 @@ printf "rm -v /opt/mow/run\n" >> /opt/mow/uninst
|
|||
printf "rm -v /opt/mow/uninst\n" >> /opt/mow/uninst
|
||||
printf "rm -v /usr/bin/mow\n" >> /opt/mow/uninst
|
||||
printf "rm -rv /opt/mow\n" >> /opt/mow/uninst
|
||||
printf "rm -r /var/opt/mow/buf\n" >> /opt/mow/uninst
|
||||
printf "deluser mow\n" >> /opt/mow/uninst
|
||||
|
||||
useradd -r mow
|
||||
|
||||
chown -R mow:mow /var/opt/mow
|
||||
chown -R -v mow:mow /var/footage
|
||||
chown -R -v mow:mow /var/buffer
|
||||
chown -R -v mow:mow /var/mow_serv
|
||||
|
||||
chmod -v +x /opt/mow/run
|
||||
chmod -v +x /opt/mow/bin
|
||||
|
|
24
setup.sh
24
setup.sh
|
@ -2,5 +2,25 @@
|
|||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt update -y
|
||||
apt install -y pkg-config cmake make g++
|
||||
apt install -y ffmpeg libavcodec-dev libavformat-dev libavutil-dev libswscale-dev x264 libx264-dev libilmbase-dev qt6-base-dev qtchooser qmake6 qt6-base-dev-tools libxkbcommon-dev libfuse-dev fuse3
|
||||
sh imgmagick_build.sh
|
||||
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
apt install -y ffmpeg
|
||||
apt install -y libavcodec-dev
|
||||
apt install -y libavformat-dev
|
||||
apt install -y libavutil-dev
|
||||
apt install -y libswscale-dev
|
||||
apt install -y x264
|
||||
apt install -y libx264-dev
|
||||
apt install -y libilmbase-dev
|
||||
apt install -y qt6-base-dev
|
||||
apt install -y qtchooser
|
||||
apt install -y qmake6
|
||||
apt install -y qt6-base-dev-tools
|
||||
apt install -y libxkbcommon-dev
|
||||
apt install -y libfuse-dev
|
||||
apt install -y fuse3
|
||||
sh imgmagick_build.sh
|
||||
fi
|
||||
|
||||
|
||||
|
|
122
src/camera.cpp
122
src/camera.cpp
|
@ -14,54 +14,24 @@
|
|||
|
||||
Camera::Camera(QObject *parent) : QObject(parent) {}
|
||||
|
||||
void Camera::cleanup()
|
||||
{
|
||||
if (QFileInfo::exists(shared.tmpDir + "/rec"))
|
||||
{
|
||||
QProcess::execute("rm", {shared.tmpDir + "/rec"});
|
||||
}
|
||||
}
|
||||
|
||||
int Camera::start(const QStringList &args)
|
||||
{
|
||||
if (rdConf(getParam("-c", args), &shared))
|
||||
{
|
||||
QProcess::execute("mkdir", {"-p", shared.outDir});
|
||||
QProcess::execute("mkdir", {"-p", shared.tmpDir});
|
||||
{
|
||||
auto thr1 = new QThread(nullptr);
|
||||
auto thr2 = new QThread(nullptr);
|
||||
auto thr3 = new QThread(nullptr);
|
||||
auto thr4 = new QThread(nullptr);
|
||||
|
||||
QProcess::execute("mkdir", {"-p", shared.tmpDir + "/live"});
|
||||
QProcess::execute("mkdir", {"-p", shared.tmpDir + "/logs"});
|
||||
QProcess::execute("mkdir", {"-p", shared.tmpDir + "/img"});
|
||||
new RecLoop(&shared, thr1, nullptr);
|
||||
new Upkeep(&shared, thr2, nullptr);
|
||||
new EventLoop(&shared, thr3, nullptr);
|
||||
new DetectLoop(&shared, thr4, nullptr);
|
||||
|
||||
cleanup();
|
||||
|
||||
touch(shared.tmpDir + "/stream.m3u8");
|
||||
|
||||
QProcess::execute("ln", {"-s", shared.outDir, shared.tmpDir + "/rec"});
|
||||
|
||||
if (!QDir::setCurrent(shared.tmpDir))
|
||||
{
|
||||
QTextStream(stderr) << "err: failed to change/create the current working directory to camera folder: '" << shared.outDir << "' does it exists?" << Qt::endl;
|
||||
|
||||
shared.retCode = ENOENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto thr1 = new QThread(nullptr);
|
||||
auto thr2 = new QThread(nullptr);
|
||||
auto thr3 = new QThread(nullptr);
|
||||
auto thr4 = new QThread(nullptr);
|
||||
|
||||
new RecLoop(&shared, thr1, nullptr);
|
||||
new Upkeep(&shared, thr2, nullptr);
|
||||
new EventLoop(&shared, thr3, nullptr);
|
||||
new DetectLoop(&shared, thr4, nullptr);
|
||||
|
||||
thr1->start();
|
||||
thr2->start();
|
||||
thr3->start();
|
||||
thr4->start();
|
||||
}
|
||||
thr1->start();
|
||||
thr2->start();
|
||||
thr3->start();
|
||||
thr4->start();
|
||||
}
|
||||
|
||||
return shared.retCode;
|
||||
|
@ -130,11 +100,15 @@ void RecLoop::updateCmd()
|
|||
{
|
||||
QStringList recArgs;
|
||||
QStringList imgArgs;
|
||||
|
||||
|
||||
recArgs << "-c";
|
||||
recArgs << buildThreadCount(shared->recThreads);
|
||||
recArgs << "ffmpeg";
|
||||
recArgs << "-hide_banner";
|
||||
recArgs << "-i" << shared->recordUri;
|
||||
recArgs << "-strftime" << "1";
|
||||
recArgs << "-strftime_mkdir" << "1";
|
||||
recArgs << "-vf" << "fps=" + QString::number(shared->recFps) + ",scale=" + shared->recScale;
|
||||
recArgs << "-hls_segment_filename" << "live/" + QString(STRFTIME_FMT) + shared->streamExt;
|
||||
recArgs << "-y";
|
||||
recArgs << "-vcodec" << shared->streamCodec;
|
||||
|
@ -142,23 +116,38 @@ void RecLoop::updateCmd()
|
|||
recArgs << "-hls_time" << "2";
|
||||
recArgs << "-hls_list_size" << "1000";
|
||||
recArgs << "-hls_flags" << "append_list+omit_endlist";
|
||||
recArgs << "-rtsp_transport" << "tcp";
|
||||
|
||||
if (shared->recordUri.contains("rtsp"))
|
||||
{
|
||||
recArgs << "-rtsp_transport" << "tcp";
|
||||
}
|
||||
|
||||
recArgs << "-t" << QString::number(heartBeat);
|
||||
recArgs << "stream.m3u8";
|
||||
|
||||
|
||||
imgArgs << "-c";
|
||||
imgArgs << buildThreadCount(shared->imgThreads);
|
||||
imgArgs << "ffmpeg";
|
||||
imgArgs << "-hide_banner";
|
||||
imgArgs << "-i" << shared->recordUri;
|
||||
imgArgs << "-strftime" << "1";
|
||||
imgArgs << "-strftime_mkdir" << "1";
|
||||
imgArgs << "-vf" << "fps=1,scale=320:240";
|
||||
imgArgs << "-rtsp_transport" << "tcp";
|
||||
imgArgs << "-vf" << "fps=1,scale=" + shared->imgScale;
|
||||
|
||||
if (shared->recordUri.contains("rtsp"))
|
||||
{
|
||||
imgArgs << "-rtsp_transport" << "tcp";
|
||||
}
|
||||
|
||||
imgArgs << "-t" << QString::number(heartBeat);
|
||||
imgArgs << "img/" + QString(STRFTIME_FMT) + ".bmp";
|
||||
|
||||
recProc->setProgram("ffmpeg");
|
||||
recProc->setWorkingDirectory(shared->tmpDir);
|
||||
recProc->setProgram("taskset");
|
||||
recProc->setArguments(recArgs);
|
||||
|
||||
imgProc->setProgram("ffmpeg");
|
||||
imgProc->setWorkingDirectory(shared->tmpDir);
|
||||
imgProc->setProgram("taskset");
|
||||
imgProc->setArguments(imgArgs);
|
||||
|
||||
recLog("rec_args: " + recArgs.join(" "), shared);
|
||||
|
@ -182,17 +171,14 @@ void RecLoop::term()
|
|||
|
||||
void RecLoop::procError(const QString &desc, QProcess *proc)
|
||||
{
|
||||
if (proc->isOpen() && (proc->state() != QProcess::Running))
|
||||
{
|
||||
auto errBlob = QString(proc->readAllStandardError());
|
||||
auto errLines = errBlob.split('\n');
|
||||
auto errBlob = QString(proc->readAllStandardError());
|
||||
auto errLines = errBlob.split('\n');
|
||||
|
||||
if (!errLines.isEmpty())
|
||||
if (!errLines.isEmpty())
|
||||
{
|
||||
for (auto &&line : errLines)
|
||||
{
|
||||
for (auto &&line : errLines)
|
||||
{
|
||||
recLog(desc + "_cmd_stderr: " + line, shared);
|
||||
}
|
||||
recLog(desc + "_cmd_stderr: " + line, shared);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -216,11 +202,11 @@ Upkeep::Upkeep(shared_t *sharedRes, QThread *thr, QObject *parent) : Loop(shared
|
|||
|
||||
bool Upkeep::exec()
|
||||
{
|
||||
enforceMaxLogSize(QString("logs/") + REC_LOG_NAME, shared);
|
||||
enforceMaxLogSize(QString("logs/") + DET_LOG_NAME, shared);
|
||||
enforceMaxLogSize(shared->tmpDir + "/logs/" + REC_LOG_NAME, shared);
|
||||
enforceMaxLogSize(shared->tmpDir + "/logs/" + DET_LOG_NAME, shared);
|
||||
|
||||
dumpLogs(QString("logs/") + REC_LOG_NAME, shared->recLog);
|
||||
dumpLogs(QString("logs/") + DET_LOG_NAME, shared->detLog);
|
||||
dumpLogs(shared->tmpDir + "/logs/" + REC_LOG_NAME, shared->recLog);
|
||||
dumpLogs(shared->tmpDir + "/logs/" + DET_LOG_NAME, shared->detLog);
|
||||
|
||||
shared->logMutex.lock();
|
||||
shared->recLog.clear();
|
||||
|
@ -228,7 +214,7 @@ bool Upkeep::exec()
|
|||
shared->logMutex.unlock();
|
||||
|
||||
enforceMaxEvents(shared);
|
||||
enforceMaxImages();
|
||||
enforceMaxImages(shared);
|
||||
enforceMaxVids(shared);
|
||||
|
||||
return Loop::exec();
|
||||
|
@ -258,7 +244,7 @@ bool EventLoop::exec()
|
|||
|
||||
args << "convert";
|
||||
args << imgPath;
|
||||
args << "rec/" + name + shared->thumbExt;
|
||||
args << shared->outDir + "/" + name + shared->thumbExt;
|
||||
|
||||
proc.start("magick", args);
|
||||
proc.waitForFinished();
|
||||
|
@ -291,8 +277,8 @@ bool EventLoop::exec()
|
|||
auto maxSecs = shared->evMaxSecs / 2;
|
||||
// half the maxsecs value to get front-back half secs
|
||||
|
||||
auto backFiles = backwardFacingFiles("live", shared->streamExt, event->timeStamp, maxSecs);
|
||||
auto frontFiles = forwardFacingFiles("live", shared->streamExt, event->timeStamp, maxSecs);
|
||||
auto backFiles = backwardFacingFiles(shared->tmpDir + "/live", shared->streamExt, event->timeStamp, maxSecs);
|
||||
auto frontFiles = forwardFacingFiles(shared->tmpDir + "/live", shared->streamExt, event->timeStamp, maxSecs);
|
||||
|
||||
vidList.append(backFiles + frontFiles);
|
||||
rmIndx.append(i);
|
||||
|
@ -351,7 +337,7 @@ bool EventLoop::wrOutVod()
|
|||
args << "-safe" << "0";
|
||||
args << "-i" << concat;
|
||||
args << "-c" << "copy";
|
||||
args << "rec/" + name + shared->recExt;
|
||||
args << shared->outDir + "/" + name + shared->recExt;
|
||||
|
||||
proc.setProgram("ffmpeg");
|
||||
proc.setArguments(args);
|
||||
|
|
|
@ -24,8 +24,6 @@ private:
|
|||
|
||||
shared_t shared;
|
||||
|
||||
void cleanup();
|
||||
|
||||
public:
|
||||
|
||||
explicit Camera(QObject *parent = nullptr);
|
||||
|
|
139
src/common.cpp
139
src/common.cpp
|
@ -107,31 +107,31 @@ QStringList forwardFacingFiles(const QString &path, const QString &ext, const QD
|
|||
|
||||
void enforceMaxEvents(shared_t *share)
|
||||
{
|
||||
auto names = lsFilesInDir("events", ".mp4");
|
||||
auto names = lsFilesInDir(share->outDir, share->recExt);
|
||||
|
||||
while (names.size() > share->maxEvents)
|
||||
{
|
||||
auto nameOnly = "events/" + names[0];
|
||||
auto nameOnly = share->outDir + "/" + names[0];
|
||||
|
||||
nameOnly.remove(".mp4");
|
||||
nameOnly.chop(share->recExt.size());
|
||||
|
||||
auto mp4File = nameOnly + ".mp4";
|
||||
auto imgFile = nameOnly + ".jpg";
|
||||
auto vidFile = nameOnly + share->recExt;
|
||||
auto imgFile = nameOnly + share->thumbExt;
|
||||
|
||||
QFile::remove(mp4File);
|
||||
QFile::remove(vidFile);
|
||||
QFile::remove(imgFile);
|
||||
|
||||
names.removeFirst();
|
||||
}
|
||||
}
|
||||
|
||||
void enforceMaxImages()
|
||||
void enforceMaxImages(shared_t *share)
|
||||
{
|
||||
auto names = lsFilesInDir("img", ".bmp");
|
||||
auto names = lsFilesInDir(share->tmpDir + "/img", ".bmp");
|
||||
|
||||
while (names.size() > MAX_IMAGES)
|
||||
{
|
||||
QFile::remove("img/" + names[0]);
|
||||
QFile::remove(share->tmpDir + "/img/" + names[0]);
|
||||
|
||||
names.removeFirst();
|
||||
}
|
||||
|
@ -139,11 +139,11 @@ void enforceMaxImages()
|
|||
|
||||
void enforceMaxVids(shared_t *share)
|
||||
{
|
||||
auto names = lsFilesInDir("live", share->streamExt);
|
||||
auto names = lsFilesInDir(share->tmpDir + "/live", share->streamExt);
|
||||
|
||||
while (names.size() > MAX_VIDEOS)
|
||||
{
|
||||
QFile::remove("live/" + names[0]);
|
||||
QFile::remove(share->tmpDir + "/live/" + names[0]);
|
||||
|
||||
names.removeFirst();
|
||||
}
|
||||
|
@ -169,22 +169,9 @@ void rdLine(const QString ¶m, const QString &line, bool *value)
|
|||
{
|
||||
if (line.startsWith(param))
|
||||
{
|
||||
*value = (line == "y" || line == "Y");
|
||||
}
|
||||
}
|
||||
|
||||
void touch(const QString &path)
|
||||
{
|
||||
if (!QFile::exists(path))
|
||||
{
|
||||
QFile file(path);
|
||||
|
||||
if (file.open(QFile::WriteOnly))
|
||||
{
|
||||
file.write("");
|
||||
}
|
||||
|
||||
file.close();
|
||||
auto val = line.mid(param.size()).trimmed();
|
||||
|
||||
*value = (val == "y" || val == "Y");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,6 +183,18 @@ void extCorrection(QString &ext)
|
|||
}
|
||||
}
|
||||
|
||||
bool mkPath(const QString &path)
|
||||
{
|
||||
auto ret = true;
|
||||
|
||||
if (!QDir().exists(path))
|
||||
{
|
||||
ret = QDir().mkpath(path);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool rdConf(const QString &filePath, shared_t *share)
|
||||
{
|
||||
QFile varFile(filePath);
|
||||
|
@ -204,13 +203,15 @@ bool rdConf(const QString &filePath, shared_t *share)
|
|||
{
|
||||
share->retCode = ENOENT;
|
||||
|
||||
QTextStream(stderr) << "err: config file: " << filePath << " does not exists or lack read permissions." << Qt::endl;
|
||||
QTextStream(stderr) << "err: config file - " << filePath << " does not exists or lack read permissions." << Qt::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
share->recordUri.clear();
|
||||
share->postCmd.clear();
|
||||
share->camName.clear();
|
||||
|
||||
auto thrCount = QThread::idealThreadCount() / 2;
|
||||
|
||||
share->retCode = 0;
|
||||
share->imgThresh = 8000;
|
||||
|
@ -220,8 +221,8 @@ bool rdConf(const QString &filePath, shared_t *share)
|
|||
share->postSecs = 60;
|
||||
share->evMaxSecs = 30;
|
||||
share->conf = filePath;
|
||||
share->buffPath = "/var/opt/" + QString(APP_BIN) + "/buf";
|
||||
share->recRoot = "/var/opt/" + QString(APP_BIN) + "/rec";
|
||||
share->buffPath = "/var/buffer";
|
||||
share->recPath = "/var/footage";
|
||||
share->outputType = "stderr";
|
||||
share->compCmd = "magick compare -metric FUZZ " + QString(PREV_IMG) + " " + QString(NEXT_IMG) + " /dev/null";
|
||||
share->streamCodec = "copy";
|
||||
|
@ -229,6 +230,11 @@ bool rdConf(const QString &filePath, shared_t *share)
|
|||
share->recExt = ".mp4";
|
||||
share->thumbExt = ".jpg";
|
||||
share->singleTenant = false;
|
||||
share->imgThreads = thrCount;
|
||||
share->recThreads = thrCount;
|
||||
share->recFps = 30;
|
||||
share->recScale = "1280:720";
|
||||
share->imgScale = "320:240";
|
||||
|
||||
QString line;
|
||||
|
||||
|
@ -241,7 +247,7 @@ bool rdConf(const QString &filePath, shared_t *share)
|
|||
rdLine("cam_name = ", line, &share->camName);
|
||||
rdLine("recording_uri = ", line, &share->recordUri);
|
||||
rdLine("buffer_path = ", line, &share->buffPath);
|
||||
rdLine("rec_root = ", line, &share->recRoot);
|
||||
rdLine("rec_path = ", line, &share->recPath);
|
||||
rdLine("max_event_secs = ", line, &share->evMaxSecs);
|
||||
rdLine("post_secs = ", line, &share->postSecs);
|
||||
rdLine("post_cmd = ", line, &share->postCmd);
|
||||
|
@ -255,6 +261,11 @@ bool rdConf(const QString &filePath, shared_t *share)
|
|||
rdLine("rec_ext = ", line, &share->recExt);
|
||||
rdLine("thumbnail_ext = ", line, &share->thumbExt);
|
||||
rdLine("single_tenant = ", line, &share->singleTenant);
|
||||
rdLine("img_threads = ", line, &share->imgThreads);
|
||||
rdLine("rec_threads = ", line, &share->recThreads);
|
||||
rdLine("rec_fps = ", line, &share->recFps);
|
||||
rdLine("rec_scale = ", line, &share->recScale);
|
||||
rdLine("img_scale = ", line, &share->imgScale);
|
||||
}
|
||||
|
||||
} while(!line.isEmpty());
|
||||
|
@ -270,16 +281,56 @@ bool rdConf(const QString &filePath, shared_t *share)
|
|||
|
||||
if (share->singleTenant)
|
||||
{
|
||||
share->outDir = QDir().cleanPath(share->recRoot);
|
||||
share->outDir = QDir().cleanPath(share->recPath);
|
||||
share->tmpDir = QDir().cleanPath(share->buffPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
share->outDir = QDir().cleanPath(share->recRoot) + "/" + share->camName;
|
||||
share->outDir = QDir().cleanPath(share->recPath) + "/" + share->camName;
|
||||
share->tmpDir = QDir().cleanPath(share->buffPath) + "/" + share->camName;
|
||||
}
|
||||
|
||||
share->servPath = QString("/var/opt/") + APP_BIN + "/" + APP_BIN + "." + share->camName + ".service";
|
||||
auto servDir = QString("/var/") + APP_BIN + QString("_serv");
|
||||
|
||||
share->retCode = EACCES;
|
||||
|
||||
if (!mkPath(servDir))
|
||||
{
|
||||
QTextStream(stderr) << "err: failed to create service directory - " << servDir << " check for write permissions." << Qt::endl;
|
||||
}
|
||||
else if (!mkPath(share->recPath))
|
||||
{
|
||||
QTextStream(stderr) << "err: failed to create root recording directory - " << share->recPath << " check for write permissions." << Qt::endl;
|
||||
}
|
||||
else if (!mkPath(share->buffPath))
|
||||
{
|
||||
QTextStream(stderr) << "err: failed to create root buffer directory - " << share->buffPath << " check for write permissions." << Qt::endl;
|
||||
}
|
||||
else if (!mkPath(share->outDir))
|
||||
{
|
||||
QTextStream(stderr) << "err: failed to create recording directory - " << share->outDir << " check for write permissions." << Qt::endl;
|
||||
}
|
||||
else if (!mkPath(share->tmpDir))
|
||||
{
|
||||
QTextStream(stderr) << "err: failed to create buffer directory - " << share->tmpDir << " check for write permissions." << Qt::endl;
|
||||
}
|
||||
else if (!mkPath(share->tmpDir + "/live"))
|
||||
{
|
||||
QTextStream(stderr) << "err: failed to create 'live' in the buffer directory - " << share->tmpDir << "/live" << " check for write permissions." << Qt::endl;
|
||||
}
|
||||
else if (!mkPath(share->tmpDir + "/logs"))
|
||||
{
|
||||
QTextStream(stderr) << "err: failed to create 'logs' in the buffer directory - " << share->tmpDir << "/logs" << " check for write permissions." << Qt::endl;
|
||||
}
|
||||
else if (!mkPath(share->tmpDir + "/img"))
|
||||
{
|
||||
QTextStream(stderr) << "err: failed to create 'img' in the buffer directory - " << share->tmpDir << "/img" << " check for write permissions." << Qt::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
share->retCode = 0;
|
||||
share->servPath = QString("/var/") + APP_BIN + QString("_serv/") + APP_BIN + "." + share->camName + ".service";
|
||||
}
|
||||
}
|
||||
|
||||
return share->retCode == 0;
|
||||
|
@ -287,7 +338,8 @@ bool rdConf(const QString &filePath, shared_t *share)
|
|||
|
||||
void rmServices()
|
||||
{
|
||||
auto files = lsFilesInDir(QString("/var/opt/") + APP_BIN, ".service");
|
||||
auto path = QString("/var/") + APP_BIN + QString("_serv");
|
||||
auto files = lsFilesInDir(path, ".service");
|
||||
|
||||
for (auto &&serv : files)
|
||||
{
|
||||
|
@ -295,7 +347,7 @@ void rmServices()
|
|||
QProcess::execute("systemctl", {"disable", serv});
|
||||
|
||||
QFile::remove(QString("/lib/systemd/system/") + serv);
|
||||
QFile::remove(QString("/var/opt/") + APP_BIN + "/" + serv);
|
||||
QFile::remove(path + "/" + serv);
|
||||
}
|
||||
|
||||
QProcess::execute("systemctl", {"daemon-reload"});
|
||||
|
@ -303,7 +355,8 @@ void rmServices()
|
|||
|
||||
void listServices()
|
||||
{
|
||||
auto files = lsFilesInDir(QString("/var/opt/") + APP_BIN, ".service");
|
||||
auto path = QString("/var/") + APP_BIN + QString("_serv");
|
||||
auto files = lsFilesInDir(path, ".service");
|
||||
|
||||
for (auto &&serv : files)
|
||||
{
|
||||
|
@ -398,6 +451,18 @@ int loadServices(const QStringList &args)
|
|||
return ret;
|
||||
}
|
||||
|
||||
QString buildThreadCount(int count)
|
||||
{
|
||||
QString ret = "0";
|
||||
|
||||
for (auto i = 1; i < count; ++i)
|
||||
{
|
||||
ret.append(","); ret.append(QString::number(i));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QStringList parseArgs(const QByteArray &data, int maxArgs, int *pos)
|
||||
{
|
||||
QStringList ret;
|
||||
|
|
14
src/common.h
14
src/common.h
|
@ -29,7 +29,7 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
#define APP_VER "3.3.t1"
|
||||
#define APP_VER "3.3.t2"
|
||||
#define APP_NAME "Motion Watch"
|
||||
#define APP_BIN "mow"
|
||||
#define REC_LOG_NAME "rec.log"
|
||||
|
@ -64,7 +64,7 @@ struct shared_t
|
|||
QString buffPath;
|
||||
QString postCmd;
|
||||
QString camName;
|
||||
QString recRoot;
|
||||
QString recPath;
|
||||
QString servPath;
|
||||
QString outputType;
|
||||
QString compCmd;
|
||||
|
@ -72,8 +72,13 @@ struct shared_t
|
|||
QString streamExt;
|
||||
QString recExt;
|
||||
QString thumbExt;
|
||||
QString recScale;
|
||||
QString imgScale;
|
||||
bool singleTenant;
|
||||
bool skipCmd;
|
||||
int recFps;
|
||||
int imgThreads;
|
||||
int recThreads;
|
||||
int evMaxSecs;
|
||||
int postSecs;
|
||||
int imgThresh;
|
||||
|
@ -83,6 +88,7 @@ struct shared_t
|
|||
};
|
||||
|
||||
QString getParam(const QString &key, const QStringList &args);
|
||||
QString buildThreadCount(int count);
|
||||
QStringList lsFilesInDir(const QString &path, const QString &ext = QString());
|
||||
QStringList lsDirsInDir(const QString &path);
|
||||
QStringList listFacingFiles(const QString &path, const QString &ext, const QDateTime &stamp, int secs, char dir);
|
||||
|
@ -90,15 +96,15 @@ QStringList backwardFacingFiles(const QString &path, const QString &ext, const Q
|
|||
QStringList forwardFacingFiles(const QString &path, const QString &ext, const QDateTime &stamp, int secs);
|
||||
QStringList parseArgs(const QByteArray &data, int maxArgs, int *pos = nullptr);
|
||||
bool rdConf(const QString &filePath, shared_t *share);
|
||||
bool mkPath(const QString &path);
|
||||
int loadServices(const QStringList &args);
|
||||
void listServices();
|
||||
void rmServices();
|
||||
void touch(const QString &path);
|
||||
void rdLine(const QString ¶m, const QString &line, QString *value);
|
||||
void rdLine(const QString ¶m, const QString &line, int *value);
|
||||
void rdLine(const QString ¶m, const QString &line, bool *value);
|
||||
void enforceMaxEvents(shared_t *share);
|
||||
void enforceMaxImages();
|
||||
void enforceMaxImages(shared_t *share);
|
||||
void enforceMaxVids(shared_t *share);
|
||||
void extCorrection(QString &ext);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user