优化录制功能以及网络通信接口

This commit is contained in:
zc 2024-08-22 00:29:39 -07:00
parent d1d8655645
commit 97f22cf302
18 changed files with 285 additions and 301 deletions

View File

@ -5,17 +5,22 @@
#include "Log.h"
#include "Tool.h"
#include <QCoreApplication>
#include <QElapsedTimer>
#include <QFileInfo>
#include <QProcess>
#include <QTime>
#include <chrono>
#include <QElapsedTimer>
LinkObject* Channel::lineIn = nullptr;
LinkObject* Channel::lineOut = nullptr;
LinkObject* Channel::rtspServer = nullptr;
LinkObject* Channel::resample = nullptr;
LinkObject* Channel::gain = nullptr;
LinkObject* Channel::volume = nullptr;
// 这里设置最大12dB增益最小30dB增益(超过12dB会爆音)
int Channel::maxGian = 12;
int Channel::minGain = -30;
int Channel::curGain = 0;
extern LinkObject* vo;
extern LinkObject* vo1;
@ -52,15 +57,29 @@ Channel::Channel(QObject* parent)
if (lineOut == nullptr) {
lineOut = Link::create("OutputAlsa");
QVariantMap dataOut;
dataOut["path"] = "hw:0,0";
dataOut["path"] = "hw:0";
lineOut->start(dataOut);
}
if (gain == nullptr) {
gain = Link::create("Gain");
gain->start();
}
if (volume == nullptr) {
volume = Link::create("Volume");
volume->start();
gain->linkA(volume);
gain->linkA(lineOut);
}
if (rtspServer == nullptr) {
rtspServer = Link::create("Rtsp");
rtspServer->start();
}
}
Channel::~Channel()
{
}
/**
* @brief
*/
@ -104,14 +123,6 @@ void Channel::init()
audioInput->start(dataAi);
audioInput->linkA(audioOutput);
// 音量
gain = Link::create("Gain");
gain->start();
volume = Link::create("Volume");
volume->start();
gain->linkA(volume);
lineOut->linkA(gain);
// 音频编码
audioEncoder = Link::create("EncodeA");
audioEncoder->start(audioEncoderParams);
@ -166,7 +177,7 @@ void Channel::init()
audioDecoder = Link::create("DecodeA");
audioDecoder->start();
if (channelName == Constant::MainChannel) {
inputFile->linkA(audioDecoder)->linkA(lineOut);
inputFile->linkA(audioDecoder)->linkA(gain);
} else {
inputFile->linkA(audioDecoder);
}
@ -182,8 +193,6 @@ void Channel::init()
*/
void Channel::startRecord()
{
QElapsedTimer mstimer;
mstimer.start();
// 记录本次录制开始时间以及当前视频录制的开始时间
QString curTime = QDateTime::currentDateTime().toString("yyyyMMddhhmmss");
startTime = curTime;
@ -198,9 +207,6 @@ void Channel::startRecord()
// 显示录制状态水印
overlay->setData(recordOverlay);
float time = (double)mstimer.nsecsElapsed() / (double)1000000;
qDebug() << channelName << "startRecord cast time:" << time << "ms";
}
/**
@ -211,7 +217,7 @@ void Channel::startRecord()
void Channel::onNewEvent(QString msg, QVariant data)
{
if (msg == "newSegment") {
int id = data.toInt();
segmentId = data.toInt();
// 将上一次的文件信息存入数据库中
DatabaseManager::File file;
file.channel = channelName == Constant::MainChannel
@ -223,7 +229,7 @@ void Channel::onNewEvent(QString msg, QVariant data)
file.day = currentTime.mid(6, 2);
file.time = currentTime.mid(8, 6);
// 设置当前视频的文件名格式本次录制开始时间_第几次分片
file.filename = QString("%1_%2.mp4").arg(startTime).arg(id - 1);
file.filename = QString("%1_%2.mp4").arg(startTime).arg(segmentId - 1);
if (db->insert(file)) {
Log::info("insert one record into database success, name: {}, channel: {}",
file.filename.toStdString(),
@ -235,6 +241,7 @@ void Channel::onNewEvent(QString msg, QVariant data)
}
// 更新当前录制录制视频的时间
currentTime = QDateTime::currentDateTime().toString("yyyyMMddhhmmss");
emit appendOneVideo(channelName);
}
}
@ -250,10 +257,11 @@ void Channel::stopRecord()
file.channel = channelName == Constant::MainChannel
? DatabaseManager::MainChannel
: DatabaseManager::SecondaryChannel;
file.year = startTime.mid(0, 4);
file.month = startTime.mid(4, 2);
file.day = startTime.mid(6, 2);
file.time = startTime.mid(8, 6);
file.year = currentTime.mid(0, 4);
file.month = currentTime.mid(4, 2);
file.day = currentTime.mid(6, 2);
file.time = currentTime.mid(8, 6);
file.filename = QString("%1_%2.mp4").arg(startTime).arg(segmentId);
overlay->setData(norecordOverlay);
}
@ -301,7 +309,7 @@ bool Channel::startPlayback(QString path)
videoDecoder->linkV(videoOutput);
// 断开音频信号输出,启动回放输出
audioInput->unLinkA(audioOutput);
audioDecoder->linkA(lineOut);
audioDecoder->linkA(gain);
playbackDuration = duration;
state = Playback;
@ -325,7 +333,7 @@ void Channel::startPlayLive()
overlay->linkV(videoOutput);
audioInput->linkA(audioOutput);
// 关闭外部音频输出
audioDecoder->unLinkA(lineOut);
audioDecoder->unLinkA(gain);
state = Stop;
}
@ -405,6 +413,7 @@ void Channel::volumeUp()
QVariantMap data;
data["gain"] = curGain;
gain->setData(data);
Log::info("current volumn gain: {}dB", curGain);
}
/**
@ -417,6 +426,7 @@ void Channel::volumeDown()
QVariantMap data;
data["gain"] = curGain;
gain->setData(data);
Log::info("current volumn gain: {}dB", curGain);
}
/**

View File

@ -17,6 +17,7 @@ public:
Finish
};
explicit Channel(QObject* parent = nullptr);
~Channel();
void init();
// 录制
@ -32,9 +33,9 @@ public:
void showFinishPromot();
// 音量
QVariantMap getVolume();
void volumeUp();
void volumeDown();
static QVariantMap getVolume();
static void volumeUp();
static void volumeDown();
public:
QString channelName;
@ -47,11 +48,11 @@ public:
static LinkObject* lineIn; // 外部音频输入
static LinkObject* resample; // 重采样
static LinkObject* lineOut; // 外部音频输出
LinkObject* gain; // 音量增益
LinkObject* volume; // 音量
int maxGian = 30;
int minGain = -30;
int curGain = 0;
static LinkObject* gain; // 音量增益
static LinkObject* volume; // 音量
static int maxGian; // 最大增益
static int minGain; // 最小增益
static int curGain; // 当前增益
LinkObject* audioInput; // 通道音频输入
LinkObject* audioOutput; // 通道音频输入
@ -85,6 +86,7 @@ private slots:
signals:
void playEnd();
void showRecordState(bool state);
void appendOneVideo(QString channelName);
private:
void loadOverlayConfig();

View File

@ -19,6 +19,7 @@ public:
static constexpr char* ConfigurationPath = "/opt/RecordControlApplication/configuration/config.json";
static constexpr char* NetConfigPath = "/opt/RecordControlApplication/configuration/net.json";
static constexpr char* NetScriptPath = "/opt/RecordControlApplication/scripts/setNetwork.sh";
static constexpr char* TimeSciptPath = "/opt/RecordControlApplication/scripts/rtc";
static constexpr char* DatabasePath = "/opt/RecordControlApplication/database/data.db";
static constexpr char* VideoPath = "/root/usb/videos";
static constexpr char* MountedPath = "/root/usb";

View File

@ -66,12 +66,13 @@ void DatabaseManager::close()
bool DatabaseManager::insert(File file)
{
QSqlQuery query;
query.prepare("insert into file (channel, name, year, month, day) values (?, ?, ?, ?, ?)");
query.prepare("insert into file (channel, year, month, day, time, filename) values (?, ?, ?, ?, ?, ?)");
query.bindValue(0, file.channel);
query.bindValue(1, file.time);
query.bindValue(2, file.year);
query.bindValue(3, file.month);
query.bindValue(4, file.day);
query.bindValue(1, file.year);
query.bindValue(2, file.month);
query.bindValue(3, file.day);
query.bindValue(4, file.time);
query.bindValue(5, file.filename);
if (query.exec()) {
return true;
} else {
@ -257,23 +258,55 @@ QStringList DatabaseManager::getAllDays(Channel chn, QString year, QString month
}
/**
* @brief
* @brief yyyyMMddhhmmss
* @param id
* @return
*/
bool DatabaseManager::remove(DatabaseManager::Channel chn, QString name)
{
int id = -1;
// 找到对应记录
QSqlQuery query;
query.prepare("delet from file where channel = ? and name = ?");
query.prepare("select * from file where channel = ? and filename = ?");
query.bindValue(0, chn);
query.bindValue(1, name);
if (query.exec()) {
while (query.next()) {
id = query.value(0).toInt();
break;
}
} else {
Log::info("cannot find the record, channel = {}, name = {}",
int(chn),
name.toStdString());
return false;
}
// 未找到
if (id == -1) {
Log::info("cannot find the record, channel = {}, name = {}",
int(chn),
name.toStdString());
return false;
}
Log::info("find the record, channel = {} , name = {}, and the id = {}",
int(chn),
name.toStdString(),
id);
query.clear();
// 删除文件
query.prepare("delete from file where id = ?");
query.bindValue(0, id);
if (query.exec()) {
Log::info("delete one record from database, id = {}, channel = {}, name = {}",
id,
int(chn),
name.toStdString());
return true;
} else {
Log::error("delete one record from database failed, channel = {}, name = {}, reason: {}",
(int)chn,
name.toStdString(),
query.lastError().databaseText().toStdString());
query.lastError().driverText().toStdString() + ", " + query.lastError().databaseText().toStdString());
return false;
}
}

137
Menu.cpp
View File

@ -32,31 +32,28 @@ Menu::Menu(QWidget* parent)
ui->cmbMonth->setView(new QListView());
ui->cmbDay->setView(new QListView());
// 设置ScrollArea为栅格布局
QGridLayout* layout = new QGridLayout(ui->scrollArea);
ui->scrollAreaWidgetContents->setLayout(layout);
// 默认设置当前操作选择主通道
curSelectChannel = DatabaseManager::MainChannel;
curPlayChannel = DatabaseManager::MainChannel;
db = DatabaseManager::getInstace();
if (!db->open())
return;
// 设置ScrollArea为栅格布局
QGridLayout* layout = new QGridLayout(ui->scrollArea);
ui->scrollAreaWidgetContents->setLayout(layout);
connect(ui->cmbYear, &QComboBox::currentTextChanged, [=](QString text) {
renderComboBoxMonth();
});
connect(ui->cmbMonth, &QComboBox::currentTextChanged, [=](QString text) {
renderComboBoxDay();
});
// 默认设置当前操作选择主通道
currentChannel = DatabaseManager::MainChannel;
QTimer::singleShot(200, [=] {
emit curChannelChanged(Constant::MainChannel);
});
}
Menu::~Menu()
{
delete ui;
delete db;
}
/**
@ -64,9 +61,9 @@ Menu::~Menu()
*/
void Menu::show()
{
QWidget::show();
renderComboBoxYear();
getContents();
QWidget::show();
}
/**
@ -75,6 +72,7 @@ void Menu::show()
*/
void Menu::setChannelSelectVisible(bool visible)
{
channelSelectVisible = visible;
ui->widget_chnSelect->setVisible(visible);
}
@ -83,7 +81,7 @@ void Menu::setChannelSelectVisible(bool visible)
*/
void Menu::renderComboBoxYear()
{
QStringList years = db->getAllYears(currentChannel);
QStringList years = db->getAllYears(curSelectChannel);
ui->cmbYear->clear();
for (auto& str : years) {
@ -101,7 +99,7 @@ void Menu::renderComboBoxMonth()
if (year.isEmpty()) {
return;
}
QStringList months = db->getAllMonths(currentChannel, year);
QStringList months = db->getAllMonths(curSelectChannel, year);
ui->cmbMonth->clear();
for (auto& str : months) {
ui->cmbMonth->addItem(str);
@ -119,7 +117,7 @@ void Menu::renderComboBoxDay()
if (year.isEmpty() || year.isEmpty()) {
return;
}
QStringList days = db->getAllDays(currentChannel, year, month);
QStringList days = db->getAllDays(curSelectChannel, year, month);
ui->cmbDay->clear();
for (auto& str : days) {
ui->cmbDay->addItem(str);
@ -133,7 +131,7 @@ void Menu::renderComboBoxDay()
void Menu::getContents()
{
QVariantMap params;
params["channel"] = currentChannel;
params["channel"] = curSelectChannel;
params["year"] = ui->cmbYear->currentText();
params["month"] = ui->cmbMonth->currentText();
params["day"] = ui->cmbDay->currentText();
@ -155,15 +153,20 @@ void Menu::renderContents()
}
// 重新生成若干个按钮
for (int i = 0; i < contentList.length(); i++) {
// 文件名格式: yyyyMMddhhmmss.mp4,只将时分秒显示到界面上
// 文件名格式: hhmmss只将时分秒显示到界面上
DatabaseManager::File file = contentList.at(i);
QPushButton* btn = new QPushButton(file.time, ui->scrollArea);
QString text = QString("%1:%2:%3").arg(file.time.mid(0, 2)).arg(file.time.mid(2, 2)).arg(file.time.mid(4, 2));
QPushButton* btn = new QPushButton(text, ui->scrollArea);
btn->setProperty("name", file.filename);
btn->setMinimumHeight(CONTENT_CELL_HEIGHT);
btn->setStyleSheet("QPushButton{border-radius: 5px;}");
btn->setCheckable(true);
btn->setAutoExclusive(true);
btn->setObjectName(QString("btn_video_%1").arg(i));
if (file.filename == curPlayFilename) {
btn->setChecked(true);
btn->setFocus();
}
int row = i / CONTENT_COLUMN;
int column = i % CONTENT_COLUMN;
layout->addWidget(btn, row, column);
@ -258,11 +261,9 @@ void Menu::confirm()
QPushButton* btn = qobject_cast<QPushButton*>(focusWidget);
btn->setChecked(true);
if (btn == ui->btn_channel_1) {
currentChannel = DatabaseManager::MainChannel;
emit curChannelChanged(Constant::MainChannel);
curSelectChannel = DatabaseManager::MainChannel;
} else {
currentChannel = DatabaseManager::SecondaryChannel;
emit curChannelChanged(Constant::SecondaryChannel);
curSelectChannel = DatabaseManager::SecondaryChannel;
}
renderComboBoxYear();
}
@ -289,7 +290,9 @@ void Menu::confirm()
btn->setChecked(true);
QString filename = btn->property("name").toString();
emit btnVideoClicked(filename);
currentFilename = filename;
// 记录当前正在回放的通道和文件名
curPlayFilename = filename;
curPlayChannel = curSelectChannel;
}
// 确认按钮按下确认
else if (focusWidget->objectName() == "btn_done") {
@ -305,45 +308,68 @@ void Menu::confirm()
/**
* @brief
*/
void Menu::clickVideo(QString type)
void Menu::clickPreOrNext(QString type)
{
getContents();
// 重新获取当前正在回放通道的视频
QVariantMap params;
params["channel"] = curPlayChannel;
params["year"] = ui->cmbYear->currentText();
params["month"] = ui->cmbMonth->currentText();
params["day"] = ui->cmbDay->currentText();
QList<DatabaseManager::File> list = db->get(params);
// 搜索当前播放视频的位置
int index = -1;
for (int i = 0; i < contentList.length(); i++) {
DatabaseManager::File file = contentList[i];
if (file.filename == currentFilename) {
for (int i = 0; i < list.length(); i++) {
DatabaseManager::File file = list[i];
if (file.filename == curPlayFilename) {
index = i;
break;
}
}
Log::info("find file filename: {}, index: {}", curPlayFilename.toStdString(), index);
// 查找目标文件名
QString filename;
// 上一个视频
if (type == "previous") {
// 已经是第一个视频了
if (index == 0) {
emit btnVideoClicked("first");
return;
}
filename = contentList[index - 1].filename;
}
// 下一个视频
else {
if (index == contentList.length() - 1) {
index -= 1;
} else {
// 已经是最后一个视频
if (index == list.length() - 1) {
emit btnVideoClicked("last");
return;
}
filename = contentList[index + 1].filename;
index += 1;
}
filename = contentList[index + 1].filename;
filename = list[index].filename;
Log::info("type: {}, index: {}, filename",
type.toStdString(),
index,
filename.toStdString());
emit btnVideoClicked(filename);
QString h = filename.mid(8, 2);
QString m = filename.mid(10, 2);
QString s = filename.mid(12, 2);
QString str = QString("%1:%2:%3").arg(h).arg(m).arg(s);
curPlayFilename = filename;
// 单通道回放
if (channelSelectVisible) {
// 选中通道和回放通道不是同一个时不处理
if (curPlayChannel != curSelectChannel) {
return;
}
}
// 双通道同时回放
else {
if (curPlayChannel != DatabaseManager::MainChannel) {
return;
}
}
// 选中要播放的按钮
QList<QPushButton*> btns = ui->scrollArea->findChildren<QPushButton*>();
for (QPushButton* btn : btns) {
if (btn->text() == str) {
if (btn->property("name").toString() == filename) {
btn->setChecked(true);
btn->setFocus();
}
}
}
@ -365,3 +391,36 @@ QList<QWidget*> Menu::getAllFocusabelWidget()
}
return result;
}
/**
* @brief
* @param channelName
*/
void Menu::onAppendOneVideo(QString channelName)
{
// 单通道
if (channelSelectVisible) {
// 只有生成新视频的通道和当前选择的通道一致时重新获取文件列表
if ((channelName == Constant::MainChannel
&& curSelectChannel == DatabaseManager::MainChannel)
|| (channelName == Constant::SecondaryChannel
&& curSelectChannel == DatabaseManager::SecondaryChannel)) {
renderContents();
}
}
// 双通道
else {
if (channelName == Constant::MainChannel) {
renderContents();
}
}
}
/**
* @brief
* @return
*/
DatabaseManager::Channel Menu::getCurPlayChannel()
{
return curSelectChannel;
}

12
Menu.h
View File

@ -18,11 +18,13 @@ public:
~Menu();
void show();
void setChannelSelectVisible(bool visible);
DatabaseManager::Channel getCurPlayChannel();
public slots:
void move(Direction direction);
void confirm();
void clickVideo(QString type);
void clickPreOrNext(QString type);
void onAppendOneVideo(QString channelName);
signals:
void btnHdmi1Checked();
@ -30,7 +32,6 @@ signals:
void btnVga1Checked();
void btnVga2Checked();
void btnVideoClicked(QString name);
void curChannelChanged(QString channel);
protected:
// 重写父类的方法,以获取当前界面的所有可以获取焦点的控件
@ -41,8 +42,11 @@ private:
// 视频名数组列表
QList<DatabaseManager::File> contentList;
DatabaseManager* db;
DatabaseManager::Channel currentChannel;
QString currentFilename;
QString curPlayFilename; // 当前正在回放的文件名
bool channelSelectVisible = false; // 是否显示通道选择,单通道回放显示、双通道不显示
DatabaseManager::Channel curSelectChannel; // 当前选择的通道
DatabaseManager::Channel curPlayChannel; // 当前回放的通道
private:
void getContents();

View File

@ -1,123 +0,0 @@
#include "Message.h"
#include <QSpacerItem>
#include <QTimer>
#include <QVBoxLayout>
Message::Message(QWidget* parent)
: QWidget(parent)
{
btnStyle = "QPushButton { \
background: rgba(0,0,0,0.4); \
color: rgba(255,255,255); \
border: none; \
border-radius: 10px; \
min-height: 40px; \
}";
QVBoxLayout* layout = new QVBoxLayout();
layout->setContentsMargins(QMargins(10, 10, 10, 10));
layout->setSpacing(10);
this->setLayout(layout);
this->setFixedHeight(260);
QFont font;
// font.setFamily("Ubuntu Regular");
font.setPixelSize(16);
this->setFont(font);
QSpacerItem* verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
layout->addSpacerItem(verticalSpacer);
}
Message::~Message()
{
}
void Message::success(QString content, int duration)
{
showMessage(content, duration, Success);
}
void Message::info(QString content, int duration)
{
showMessage(content, duration, Info);
}
void Message::error(QString content, int duration)
{
showMessage(content, duration, Error);
}
void Message::warning(QString content, int duration)
{
showMessage(content, duration, Warning);
}
void Message::showMessage(QString content, int duration, Level level)
{
QVBoxLayout* layout = static_cast<QVBoxLayout*>(this->layout());
if (count >= maxCount) {
// remove first
QPair<QPushButton*, QTimer*> pair = contentList.first();
contentList.removeFirst();
layout->removeWidget(pair.first);
delete pair.first;
delete pair.second;
count -= 1;
}
// apeend new
QPushButton* btn = generateButton(content, level);
layout->insertWidget(count, btn);
QTimer* timer = new QTimer();
timer->setInterval(duration);
timer->start();
QPair<QPushButton*, QTimer*> pair(btn, timer);
contentList.append(pair);
count += 1;
connect(timer, &QTimer::timeout, [=] {
for (int i = 0; i < contentList.length(); i++) {
QPair<QPushButton*, QTimer*> pair = contentList.at(i);
if (pair.first == btn) {
contentList.removeAt(i);
}
layout->removeWidget(pair.first);
delete pair.first;
delete pair.second;
}
});
}
QPushButton* Message::generateButton(QString content, Level level)
{
QPushButton* btn = new QPushButton(this);
btn->setText(content);
QString iconPath;
switch (level) {
case Info:
iconPath = ":/icons/info.png";
break;
case Success:
iconPath = ":/icons/success.png";
break;
case Error:
iconPath = ":/icons/error.png";
case Warning:
iconPath = ":/icons/waring.png";
break;
default:
iconPath = ":/icons/info.png";
break;
}
btn->setIcon(QIcon(iconPath));
btn->setIconSize(QSize(16, 16));
btn->setStyleSheet(btnStyle);
QFont font = btn->font();
QFontMetrics metrics(font);
int width = metrics.boundingRect(content).size().width();
btn->setFixedWidth(width);
return btn;
}

View File

@ -1,43 +0,0 @@
#ifndef MESSAGE_H
#define MESSAGE_H
#include <QLabel>
#include <QPair>
#include <QPushButton>
#include <QTimer>
#include <QWidget>
class Message : public QWidget {
Q_OBJECT
public:
enum Level {
Success,
Error,
Info,
Warning
};
explicit Message(QWidget* parent = 0);
~Message();
void success(QString content, int duration);
void error(QString content, int duration);
void info(QString content, int duration);
void warning(QString content, int duration);
private:
Level level = Info;
bool isShow = false;
int count = 0;
int maxCount = 5;
QList<QPair<QPushButton*, QTimer*>> contentList;
QString btnStyle;
private:
void showMessage(QString content, int duration, Level level);
QPushButton* generateButton(QString content, Level level);
};
#endif // MESSAGE_H

View File

@ -44,7 +44,6 @@ private:
inline QString ProgressBar::msecToString(int msc)
{
QString formatStr = QTime(0, 0, 0).addMSecs(msc).toString(QString::fromUtf8("hh:mm:ss"));
qDebug() << msc;
return formatStr;
}

View File

@ -35,7 +35,6 @@ SOURCES += \
Channel.cpp \
Menu.cpp\
ProgressBar.cpp \
Message.cpp \
Tool.cpp \
CheckStorageThread.cpp \
Constant.h \
@ -54,7 +53,6 @@ HEADERS += \
Channel.h \
Menu.h \
ProgressBar.h \
Message.h \
Tool.h \
CheckStorageThread.h \
Log.h \

View File

@ -182,6 +182,12 @@ void SerialPortTool::onReayRead()
// 返回
emit btnReturnClicked();
break;
case 8:
emit btnVolumnUpClicked();
break;
case 9:
emit btnVolumnDownClicked();
break;
default:
break;
}
@ -240,11 +246,13 @@ void SerialPortTool::onDiskNotFull()
serialPort->write(cmdMap.value(DiskNotFull));
serialPort->flush();
}
void SerialPortTool::onPowerOn()
{
serialPort->write(cmdMap.value(PowerOn));
serialPort->flush();
}
void SerialPortTool::onPowerOff()
{
serialPort->write(cmdMap.value(PowerOff));

View File

@ -51,6 +51,8 @@ signals:
void btnRightClicked();
void btnConfirmClicked();
void btnReturnClicked();
void btnVolumnUpClicked();
void btnVolumnDownClicked();
private:
enum CommandType {

View File

@ -23,6 +23,7 @@ void TcpConnectionHandler::onReadyRead()
{
bool ret = request->readFromSocket(socket);
if (!ret) {
response->setUrl("Unkown Url");
response->error(request->getErrorString());
return;
}

View File

@ -5,6 +5,7 @@
#include "Json.h"
#include "Log.h"
#include "Tool.h"
#include <QCoreApplication>
#include <QDir>
#include <QProcess>
@ -183,7 +184,7 @@ void TcpRequestHandler::getFileList(TcpRequest* request, TcpResponse* reponse)
{
QVariantMap params = request->getBodyParams();
QString chn = params.value("interface").toString();
if (chn != Constant::MainChannel || chn != Constant::SecondaryChannel) {
if (chn != Constant::MainChannel && chn != Constant::SecondaryChannel) {
Log::error("getFileList params error, error param \"interface\"");
reponse->error("接口参数错误");
return;
@ -192,11 +193,15 @@ void TcpRequestHandler::getFileList(TcpRequest* request, TcpResponse* reponse)
: DatabaseManager::SecondaryChannel;
QString interface = params.value("interface").toString();
QList<DatabaseManager::File> fileList = db->get(channel);
QStringList result;
QVariantList result;
for (const DatabaseManager::File& file : fileList) {
result.push_back(file.filename);
QString time = file.year + file.month + file.day + file.time;
QVariantMap fileInfo;
fileInfo["time"] = time;
fileInfo["filename"] = file.filename;
result.push_back(fileInfo);
}
reponse->success("获取文件成功", result);
reponse->success("获取文件成功", QVariant::fromValue(result));
}
/**
@ -208,7 +213,7 @@ void TcpRequestHandler::deleteFile(TcpRequest* request, TcpResponse* reponse)
QVariantMap params = request->getBodyParams();
QString chn = params.value("interface").toString();
QString filename = params.value("filename").toString();
if (chn != Constant::MainChannel || chn != Constant::SecondaryChannel) {
if (chn != Constant::MainChannel && chn != Constant::SecondaryChannel) {
Log::error("deleteFile params error, error params \"interface\" or \"filename\"");
reponse->error("通道参数错误");
return;
@ -218,18 +223,24 @@ void TcpRequestHandler::deleteFile(TcpRequest* request, TcpResponse* reponse)
reponse->error("缺少文件名参数");
return;
}
// 从数据库删除指定记录
DatabaseManager::Channel channel = chn == Constant::MainChannel
? DatabaseManager::MainChannel
: DatabaseManager::SecondaryChannel;
db->remove(channel, filename);
// 删除相对于的视频文件
// 先查找是否存在物理文件,再查找数据库中是否有对应记,然后一一删除
// 删除对应的视频文件
QString filePath = QString("%1/%2/%3").arg(Constant::VideoPath).arg(chn).arg(filename);
QFile video(filePath);
if (video.exists()) {
// 删除数据库记录
DatabaseManager::Channel channel = chn == Constant::MainChannel
? DatabaseManager::MainChannel
: DatabaseManager::SecondaryChannel;
bool ret = db->remove(channel, filename);
if (!ret) {
reponse->error("文件不存在");
return;
} else {
video.remove();
Log::info("remove video {}", filePath.toStdString());
reponse->success("删除成功");
}
} else {
Log::error("error, file: {} dont exist", filePath.toStdString());
reponse->error("文件不存在");
@ -315,9 +326,7 @@ void TcpRequestHandler::reboot(TcpRequest* request, TcpResponse* reponse)
chn->stopRecord();
}
reponse->success("重启成功");
// 退出程序等待后台运行的shell脚本重启程序
exit(0);
qApp->quit();
}
/**
@ -334,7 +343,7 @@ void TcpRequestHandler::setCurrentTime(TcpRequest* request, TcpResponse* reponse
}
QString time = params.value("time").toString();
QString cmd = QString("/link/bin/rtc -s time %1").arg(time);
QString cmd = QString("%1 -s time \"%2\"").arg(Constant::TimeSciptPath).arg(time);
QString result = Tool::writeCom(cmd);
// 修改成功会返回类似信息, "Tue Mar 5 15:51:18 CST 2024"
if (result.isEmpty()) {

View File

@ -1,4 +1,5 @@
#include "Tool.h"
#include "QTimer"
#include <QDebug>
#include <QDir>
#include <QElapsedTimer>

View File

@ -46,6 +46,7 @@ Widget::Widget(QWidget* parent)
for (Channel* chn : channelList) {
connect(chn, SIGNAL(playEnd()), this, SLOT(onPlayEnd()));
connect(chn, SIGNAL(showRecordState(bool)), this, SLOT(onShowRecordLabel(bool)));
connect(chn, SIGNAL(appendOneVideo(QString)), menu, SLOT(onAppendOneVideo(QString)));
// 监听输入信号的变化
connect(chn->videoInput, &LinkObject::newEvent, [=](QString type, QVariant msg) {
if (type == "signal") {
@ -81,10 +82,11 @@ Widget::Widget(QWidget* parent)
connect(serialPortTool, SIGNAL(btnRightClicked()), this, SLOT(onBtnRightClicked()));
connect(serialPortTool, SIGNAL(btnConfirmClicked()), this, SLOT(onBtnConfirmClicked()));
connect(serialPortTool, SIGNAL(btnReturnClicked()), this, SLOT(onBtnReturnClicked()));
connect(serialPortTool, SIGNAL(btnVolumnUpClicked()), this, SLOT(onBtnVolumnUpClicked()));
connect(serialPortTool, SIGNAL(btnVolumnDownClicked()), this, SLOT(onBtnVolumnDownClicked()));
connect(menu, SIGNAL(curChannelChanged(QString)), this, SLOT(onCurChannelChanged(QString)));
connect(menu, SIGNAL(btnVideoClicked(QString)), this, SLOT(onBtnVideoClicked(QString)));
connect(this, SIGNAL(needPlayVideo(QString)), menu, SLOT(clickVideo(QString)));
connect(this, SIGNAL(needPlayVideo(QString)), menu, SLOT(clickPreOrNext(QString)));
}
Widget::~Widget()
@ -134,7 +136,6 @@ void Widget::onBtnReturnClicked()
if (chn->state != Channel::Stop) {
chn->startPlayLive();
serialPortTool->onPlaybackEnd();
curPlayFilename = "";
}
}
// 隐藏进度条并关闭定时器
@ -232,12 +233,29 @@ void Widget::onBtnConfirmClicked()
}
}
/**
* @brief
*/
void Widget::onBtnVolumnUpClicked()
{
Channel::volumeUp();
}
/**
* @brief
*/
void Widget::onBtnVolumnDownClicked()
{
Channel::volumeDown();
}
/**
* @brief
*/
void Widget::onBtnVideoClicked(QString filename)
{
if (filename == "first") {
qDebug() << "click previous failed, already the first video";
// 显示提示弹窗
} else if (filename == "last") {
if (playbackMode == Constant::OneChannelPlayback) {
@ -257,18 +275,16 @@ void Widget::onBtnVideoClicked(QString filename)
}
}
void Widget::onCurChannelChanged(QString channel)
{
curSelectChannel = channel;
Log::info("channel switch, current channel:", channel.toStdString());
}
/**
* @brief HDMI-OUT0口输出
*/
void Widget::playOneChannel(QString filename)
{
QString path = QString("%1/%2/%3").arg(Constant::VideoPath).arg(curSelectChannel).arg(filename);
// 获取当前回放的通道
QString curPlayChannel = menu->getCurPlayChannel() == DatabaseManager::MainChannel
? Constant::MainChannel
: Constant::SecondaryChannel;
QString path = QString("%1/%2/%3").arg(Constant::VideoPath).arg(curPlayChannel).arg(filename);
Channel* channel = findChannelByName(Constant::MainChannel);
for (Channel* chn : channelList) {
chn->startPlayLive();
@ -280,10 +296,7 @@ void Widget::playOneChannel(QString filename)
}
isPlayback = true;
curPlayChannel = curSelectChannel;
curPlayFilename = filename;
// 全局保存当前播放的视频
// 全局保存当前播放的视频的文件名
mutex.lock();
curFilename = filename;
condition.wakeAll();
@ -334,12 +347,8 @@ void Widget::playTwoChannels(QString filename)
}
}
}
curPlayFilename = filename;
curPlayChannel = Constant::MainChannel;
isPlayback = true;
// 全局保存正在播放的视频
// 全局保存正在播放的视频的文件名
mutex.lock();
curFilename = filename;
condition.wakeAll();
@ -374,6 +383,8 @@ void Widget::seek(QString type)
*/
void Widget::onPlayEnd()
{
// 停下回放计时器
progressTimer->stop();
// 当两路回放时,只处理一次槽函数
if (playbackMode == Constant::TwoChannelPlayback) {
LinkObject* file = static_cast<LinkObject*>(sender());

View File

@ -3,7 +3,6 @@
#include "Channel.h"
#include "Menu.h"
#include "Message.h"
#include "ProgressBar.h"
#include <QDir>
#include <QMap>
@ -36,20 +35,17 @@ private slots:
void onBtnRightClicked();
void onBtnConfirmClicked();
void onBtnReturnClicked();
void onBtnVolumnUpClicked();
void onBtnVolumnDownClicked();
// 播放视频
void onBtnVideoClicked(QString filename);
void onCurChannelChanged(QString channel);
private:
Ui::Widget* ui;
QTimer* progressTimer;
bool isPlayback = false;
QString curPlayChannel;
QString curSelectChannel;
QString curPlayFilename;
Menu* menu;
private:

View File

@ -23,6 +23,8 @@ DatabaseManager* db;
// 视频输出通道
LinkObject* vo;
LinkObject* vo1;
// 硬盘检测现场
CheckStorageThread* thread;
// 通道列表
QList<Channel*> channelList;
@ -135,6 +137,20 @@ void setChannelProtocol()
int main(int argc, char* argv[])
{
qDebug() << (R"(
____ _ _____
/ ___|| |__ __ _ _ __ | ___|__ _ __ __ _
\___ \| '_ \ / _` | '_ \| |_ / _ \ '_ \ / _` |
___) | | | | (_| | | | | _| __/ | | | (_| |
|____/|_| |_|\__,_|_| |_|_| \___|_| |_|\__, |
|___/ )");
qDebug() << (R"(
____ _ _ _ __ __ _
/ ___|| |_ __ _ _ __| |_ ___ __| | \ \ / /__| | ___ ___ _ __ ___ ___
\___ \| __/ _` | '__| __/ _ \/ _` | \ \ /\ / / _ \ |/ __/ _ \| '_ ` _ \ / _ \
___) | || (_| | | | || __/ (_| | \ V V / __/ | (_| (_) | | | | | | __/
|____/ \__\__,_|_| \__\___|\__,_| \_/\_/ \___|_|\___\___/|_| |_| |_|\___|
)");
// std::atexit(resetLight);
// 初始化日志
Log::init();
@ -218,7 +234,7 @@ int main(int argc, char* argv[])
w.show();
// 硬盘检测线程,检测硬盘容量
CheckStorageThread* thread = new CheckStorageThread();
thread = new CheckStorageThread();
thread->start();
QObject::connect(thread, SIGNAL(diskWillFull()), serialPortTool, SLOT(onDiskWillFull()));
QObject::connect(thread, SIGNAL(diskNotFull()), serialPortTool, SLOT(onDiskNotFull()));