指示灯和按钮串口通讯部分调试完成

This commit is contained in:
zc 2024-05-11 00:40:07 -07:00
parent 77cbb4ad3d
commit ba3b79a076
16 changed files with 699 additions and 80 deletions

View File

@ -2,6 +2,7 @@
#include "Constant.h" #include "Constant.h"
#include "Log.h" #include "Log.h"
#include "Tool.h" #include "Tool.h"
#include <QCoreApplication>
#include <QFileInfo> #include <QFileInfo>
#include <QProcess> #include <QProcess>
#include <QTime> #include <QTime>
@ -10,6 +11,7 @@
LinkObject* Channel::audioInput = nullptr; LinkObject* Channel::audioInput = nullptr;
LinkObject* Channel::audioOutput = nullptr; LinkObject* Channel::audioOutput = nullptr;
LinkObject* Channel::rtspServer = nullptr; LinkObject* Channel::rtspServer = nullptr;
QString Channel::curRecordFilename = "";
extern LinkObject* vo; extern LinkObject* vo;
extern LinkObject* vo1; extern LinkObject* vo1;
@ -85,11 +87,20 @@ void Channel::init()
dataMp4["format"] = "mp4"; dataMp4["format"] = "mp4";
dataMp4["segmentDuration"] = duration; dataMp4["segmentDuration"] = duration;
dataMp4["lowLatency"] = true; dataMp4["lowLatency"] = true;
dataMp4["filecache"] = 20480000; // dataMp4["filecache"] = 20480000;
record->setData(dataMp4); record->setData(dataMp4);
videoInput->linkV(videoEncoder)->linkV(record); videoInput->linkV(videoEncoder)->linkV(record);
audioInput->linkA(audioEncoder)->linkA(record); audioInput->linkA(audioEncoder)->linkA(record);
connect(record, &LinkObject::newEvent, [=](QString type, QVariant data) {
if (type == "newSegment") {
int id = data.toInt();
curRecordFilename = QString("%1_%2.mp4")
.arg(curRecordFilename.split("_")[0])
.arg(id, 2, 10, QLatin1Char('0'));
}
});
// rstp流 // rstp流
rtsp = Link::create("Mux"); rtsp = Link::create("Mux");
QVariantMap dataRtsp; QVariantMap dataRtsp;
@ -128,9 +139,12 @@ void Channel::init()
*/ */
void Channel::startRecord() void Channel::startRecord()
{ {
// 阻塞到整分钟才开始录制,方便上位机进行回放
while (int secs = QTime::currentTime().second() % 60 != 0) { while (int secs = QTime::currentTime().second() % 60 != 0) {
QCoreApplication::processEvents();
} }
QString curTime = QDateTime::currentDateTime().toString("yyyyMMddhhmm"); QString curTime = QDateTime::currentDateTime().toString("yyyyMMddhhmm");
curRecordFilename = curTime + "_00.mp4";
QVariantMap dataRecord; QVariantMap dataRecord;
QString path = QString("%1/%2/%3.mp4").arg(Constant::VideoPath).arg(channelName).arg(curTime + "_%02d"); QString path = QString("%1/%2/%3.mp4").arg(Constant::VideoPath).arg(channelName).arg(curTime + "_%02d");
dataRecord["path"] = path; dataRecord["path"] = path;

View File

@ -31,10 +31,11 @@ public:
QVariantMap audioEncoderParams; QVariantMap audioEncoderParams;
LinkObject* record; LinkObject* record;
// 单个视频时长 int duration = 1 * 60 * 1000; // 单个视频时长
int duration = 1 * 60 * 1000;
bool isRecord = false; bool isRecord = false;
static QString curRecordFilename; // 当前正在录制的文件名
int playbackDuration = 0;
LinkObject* file; LinkObject* file;
LinkObject* image; LinkObject* image;
LinkObject* videoDecoder; LinkObject* videoDecoder;
@ -47,15 +48,12 @@ public:
void startRecord(); void startRecord();
void stopRecord(); void stopRecord();
int playbackDuration = 0;
bool startPlayback(QString path); bool startPlayback(QString path);
void forward(); void forward();
void back(); void back();
void togglePause(); void togglePause();
void startPlayLive(); void startPlayLive();
void showFinishPromot(); void showFinishPromot();
signals: signals:

140
ChannelSetting.cpp Normal file
View File

@ -0,0 +1,140 @@
#include "ChannelSetting.h"
#include "Constant.h"
#include "SerialPortTool.h"
#include "ui_ChannelSetting.h"
#include <Json.h>
#include <QApplication>
#include <QDebug>
#include <QKeyEvent>
#include <QThread>
extern SerialPortTool* serialPortTool;
ChannelSetting::ChannelSetting(QWidget* parent)
: QWidget(parent)
, ui(new Ui::ChannelSetting)
{
ui->setupUi(this);
QPoint globalPos = parent->mapToGlobal(QPoint(0, 0));
int x = globalPos.x() + (parent->width() - this->width()) / 2;
int y = globalPos.y() + (parent->height() - this->height()) / 2;
this->move(x, y);
}
ChannelSetting::~ChannelSetting()
{
delete ui;
}
/**
* @brief show方法
*/
void ChannelSetting::show()
{
// 默认聚焦确定按钮
ui->btnDone->setFocus();
// 获取配置文件中保存的输入源类型(HDMI or VGA)
QVariantMap config = Json::loadFile(Constant::ConfigurationPath).toMap();
QVariantList list = config["interface"].toList();
for (int i = 0; i < list.count(); i++) {
QVariantMap cfg = list.at(i).toMap();
QString channelName = cfg["name"].toString();
QString protocol = cfg["protocol"].toString();
if (channelName == Constant::MainChannel) {
protocol1 = protocol;
} else {
protocol2 = protocol;
}
}
if (protocol1 == "HDMI") {
ui->btn_hdmi_1->setChecked(true);
} else {
ui->btn_vga_1->setChecked(true);
}
if (protocol2 == "HDMI") {
ui->btn_hdmi_2->setChecked(true);
} else {
ui->btn_vga_2->setChecked(true);
}
QWidget::show();
}
void ChannelSetting::onReceiveNext()
{
QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier);
QApplication::sendEvent(focusWidget(), &keyEvent);
QKeyEvent keyEvent1(QEvent::KeyRelease, Qt::Key_Down, Qt::NoModifier);
QApplication::sendEvent(focusWidget(), &keyEvent1);
}
void ChannelSetting::onReceivePre()
{
QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier);
QApplication::sendEvent(focusWidget(), &keyEvent);
QKeyEvent keyEvent1(QEvent::KeyRelease, Qt::Key_Up, Qt::NoModifier);
QApplication::sendEvent(focusWidget(), &keyEvent1);
}
void ChannelSetting::onReceiveEnter()
{
// 聚焦的控件
QString objName = focusWidget()->objectName();
// 通道一
if (objName.endsWith("1")) {
if (objName == "btn_hdmi_1") {
ui->btn_hdmi_1->setChecked(true);
ui->btn_vga_1->setChecked(false);
protocol1 = "HDMI";
} else {
ui->btn_hdmi_1->setChecked(false);
ui->btn_vga_1->setChecked(true);
protocol1 = "VGA";
}
}
// 通道二
else if (objName.endsWith("2")) {
if (objName == "btn_hdmi_2") {
ui->btn_hdmi_2->setChecked(true);
ui->btn_vga_2->setChecked(false);
protocol2 = "HDMI";
} else {
ui->btn_hdmi_2->setChecked(false);
ui->btn_vga_2->setChecked(true);
protocol2 = "VGA";
}
}
// 确认按钮
else {
// 保存配置
QVariantMap config = Json::loadFile(Constant::ConfigurationPath).toMap();
QVariantList list = config["interface"].toList();
for (int i = 0; i < list.count(); i++) {
QVariantMap cfg = list.at(i).toMap();
QString channelName = cfg["name"].toString();
if (channelName == Constant::MainChannel) {
cfg["protocol"] = protocol1;
} else {
cfg["protocol"] = protocol2;
}
list[i] = cfg;
}
config["interface"] = list;
Json::saveFile(config, Constant::ConfigurationPath);
// 发送指令
if (protocol1 == "HDMI") {
serialPortTool->onMainChannelHDMI();
} else {
serialPortTool->onMainChannelVGA();
}
QThread::msleep(100);
if (protocol2 == "HDMI") {
serialPortTool->onSecondaryChannelHDMI();
} else {
serialPortTool->onSecondaryChannelVGA();
}
hide();
}
}

29
ChannelSetting.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef CHANNELSETTING_H
#define CHANNELSETTING_H
#include <QWidget>
namespace Ui {
class ChannelSetting;
}
class ChannelSetting : public QWidget {
Q_OBJECT
public:
explicit ChannelSetting(QWidget* parent = 0);
~ChannelSetting();
void show();
public slots:
void onReceiveEnter();
void onReceivePre();
void onReceiveNext();
private:
Ui::ChannelSetting* ui;
QString protocol1; // 通道1输入信号类型
QString protocol2; // 通道2输入信号类型
};
#endif // CHANNELSETTING_H

269
ChannelSetting.ui Normal file
View File

@ -0,0 +1,269 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ChannelSetting</class>
<widget class="QWidget" name="ChannelSetting">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>391</width>
<height>307</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<property name="styleSheet">
<string notr="true">QPushButton {
outline: none;
border: none;
}
QPushButton:focus {
border: 5px solid red;
}
QPushButton:checked {
background: blue;
}</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="0">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="widget" native="true">
<property name="styleSheet">
<string notr="true">QWidget {
color: #ffffff;
}
QWidget#widget{
background: rgba(0, 0, 0, 0.8);
}
QPushButton {
outline: none;
border: none;
background: rgba(100,100,100,0.8);
}
QPushButton:focus {
border: 5px solid red;
}
QPushButton:checked {
background: rgba(0,0,255,0.8);
}</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string> 视频源设置</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="2,3">
<item>
<widget class="QLabel" name="label_2">
<property name="maximumSize">
<size>
<width>16777213</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>通道1</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="topMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
<item>
<widget class="QPushButton" name="btn_hdmi_1">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>HDMI</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_vga_1">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>VGA</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="2,3">
<item>
<widget class="QLabel" name="label_3">
<property name="maximumSize">
<size>
<width>16777213</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>通道2</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="topMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
<item>
<widget class="QPushButton" name="btn_hdmi_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>HDMI</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_vga_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>VGA</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="btnDone">
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true">background: rgba(0,0,255,0.8);</string>
</property>
<property name="text">
<string>确定</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -46,11 +46,15 @@ void CheckStorageThread::run()
bool ret = Tool::removeFile(path); bool ret = Tool::removeFile(path);
if (!ret) { if (!ret) {
Log::error("remove file {} failed", path.toStdString()); Log::error("remove file {} failed", path.toStdString());
} else {
Log::info("remove file {} success", path.toStdString());
} }
path = QString("%1/%2/%3").arg(Constant::VideoPath).arg(Constant::SecondaryChannel).arg(filename); path = QString("%1/%2/%3").arg(Constant::VideoPath).arg(Constant::SecondaryChannel).arg(filename);
ret = Tool::removeFile(path); ret = Tool::removeFile(path);
if (!ret) { if (!ret) {
Log::error("remove file {} failed", path.toStdString()); Log::error("remove file {} failed", path.toStdString());
} else {
Log::info("remove file {} success", path.toStdString());
} }
} }
} else { } else {

View File

@ -23,8 +23,8 @@ public:
static constexpr char* ErrorImagePath = "/opt/RecordControlApplication/images/error.jpeg"; static constexpr char* ErrorImagePath = "/opt/RecordControlApplication/images/error.jpeg";
static constexpr char* EmptyImagePath = "/opt/RecordControlApplication/images/empty.jpeg"; static constexpr char* EmptyImagePath = "/opt/RecordControlApplication/images/empty.jpeg";
static constexpr char* FinishImagePath = "/opt/RecordControlApplication/images/finish.jpeg"; static constexpr char* FinishImagePath = "/opt/RecordControlApplication/images/finish.jpeg";
static constexpr char* MainChannel = "HDMI-A"; static constexpr char* MainChannel = "HDMI-C";
static constexpr char* SecondaryChannel = "HDMI-B"; static constexpr char* SecondaryChannel = "HDMI-D";
}; };
#endif // CONSTANT_H #endif // CONSTANT_H

View File

@ -21,12 +21,13 @@
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">QPushButton { <string notr="true">QPushButton {
border: none; border: none;
background: rgba(0, 0, 0, 0.4); background: rgba(0, 0, 0, 0.8);
color: #ffffff; color: #ffffff;
} }
QPushButton::checked{ QPushButton::checked{
color: #00AEEC; /*color: #1668dc;*/
color:#3c89e8;
}</string> }</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">

View File

@ -44,7 +44,8 @@ SOURCES += \
TcpConnectionHandler.cpp \ TcpConnectionHandler.cpp \
TcpRequestHandler.cpp \ TcpRequestHandler.cpp \
TcpResponse.cpp \ TcpResponse.cpp \
SerialPortTool.cpp SerialPortTool.cpp \
ChannelSetting.cpp
HEADERS += \ HEADERS += \
Widget.h \ Widget.h \
@ -60,12 +61,14 @@ HEADERS += \
TcpConnectionHandler.h \ TcpConnectionHandler.h \
TcpRequestHandler.h \ TcpRequestHandler.h \
TcpResponse.h \ TcpResponse.h \
SerialPortTool.h SerialPortTool.h \
ChannelSetting.h
FORMS += \ FORMS += \
Menu.ui \ Menu.ui \
ProgressBar.ui \ ProgressBar.ui \
Widget.ui Widget.ui \
ChannelSetting.ui
RESOURCES += \ RESOURCES += \
res.qrc res.qrc

View File

@ -14,28 +14,43 @@ SerialPortTool::SerialPortTool(QObject* parent)
timer->stop(); timer->stop();
connect(timer, SIGNAL(timeout()), this, SLOT(onTimeout())); connect(timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
auto makeCommand = [=](QString lightNum, QString enable) { auto makeCommand = [=](int type, QString data, QString enable) {
return QByteArray::fromHex(QString("A2 B2 08 02 %1 %2 C2 D2").arg(lightNum).arg(enable).toLatin1()); // 命令类型
QString t;
if (type == 2)
t = "02"; // 指示灯
else
t = "03"; // 使能
return QByteArray::fromHex(QString("A2 B2 08 %1 %2 %3 C2 D2")
.arg(t)
.arg(data)
.arg(enable)
.toLatin1());
}; };
cmdMap[PlaybackStart] = makeCommand("01", "01"); cmdMap[Reset] = makeCommand(2, "00", "00");
cmdMap[PlaybackEnd] = makeCommand("01", "00"); cmdMap[PlaybackStart] = makeCommand(2, "01", "01");
cmdMap[RecordStart] = makeCommand("02", "01"); cmdMap[PlaybackEnd] = makeCommand(2, "01", "00");
cmdMap[RecordEnd] = makeCommand("02", "00"); cmdMap[RecordStart] = makeCommand(2, "02", "01");
cmdMap[PlayPause] = makeCommand("03", "01"); cmdMap[RecordEnd] = makeCommand(2, "02", "00");
cmdMap[PlayResume] = makeCommand("03", "00"); cmdMap[PlayPause] = makeCommand(2, "03", "01");
cmdMap[DiskWillFull] = makeCommand("04", "01"); cmdMap[PlayResume] = makeCommand(2, "03", "00");
cmdMap[DiskNotFull] = makeCommand("04", "00"); cmdMap[DiskWillFull] = makeCommand(2, "04", "01");
cmdMap[PowerOn] = makeCommand("05", "01"); cmdMap[DiskNotFull] = makeCommand(2, "04", "00");
cmdMap[PowerOff] = makeCommand("05", "00"); cmdMap[PowerOn] = makeCommand(2, "05", "01");
cmdMap[Forward] = makeCommand("06", "01"); cmdMap[PowerOff] = makeCommand(2, "05", "00");
cmdMap[LoopOn] = makeCommand("07", "01"); cmdMap[Forward] = makeCommand(2, "08", "01");
cmdMap[LoopOff] = makeCommand("07", "00"); cmdMap[LoopOn] = makeCommand(2, "07", "01");
cmdMap[Back] = makeCommand("08", "01"); cmdMap[LoopOff] = makeCommand(2, "07", "00");
cmdMap[MainChannelOn] = makeCommand("09", "01"); cmdMap[Back] = makeCommand(2, "06", "01");
cmdMap[MainChannelOff] = makeCommand("09", "00"); cmdMap[MainChannelOn] = makeCommand(2, "09", "01");
cmdMap[SecondaryChannelOn] = makeCommand("0A", "01"); cmdMap[MainChannelOff] = makeCommand(2, "09", "00");
cmdMap[SecondaryChannelOff] = makeCommand("0A", "00"); cmdMap[SecondaryChannelOn] = makeCommand(2, "0A", "01");
cmdMap[SecondaryChannelOff] = makeCommand(2, "0A", "00");
cmdMap[MainChannelHDMI] = makeCommand(3, "03", "00");
cmdMap[MainChannelVGA] = makeCommand(3, "03", "01");
cmdMap[SecondaryChannelHDMI] = makeCommand(3, "04", "00");
cmdMap[SecondaryChanneVGA] = makeCommand(3, "04", "01");
} }
SerialPortTool::~SerialPortTool() SerialPortTool::~SerialPortTool()
@ -163,11 +178,20 @@ void SerialPortTool::onReayRead()
case 8: case 8:
emit btnDoneClicked(); emit btnDoneClicked();
break; break;
case 9:
emit btnChannelSettingClicked();
break;
default: default:
break; break;
} }
} }
void SerialPortTool::onReset()
{
serialPort->write(cmdMap.value(Reset));
serialPort->flush();
}
void SerialPortTool::onPlaybackStart() void SerialPortTool::onPlaybackStart()
{ {
serialPort->write(cmdMap.value(PlaybackStart)); serialPort->write(cmdMap.value(PlaybackStart));
@ -273,3 +297,27 @@ void SerialPortTool::onSecondaryChannelOff()
serialPort->write(cmdMap.value(SecondaryChannelOff)); serialPort->write(cmdMap.value(SecondaryChannelOff));
serialPort->flush(); serialPort->flush();
} }
void SerialPortTool::onMainChannelHDMI()
{
serialPort->write(cmdMap.value(MainChannelHDMI));
serialPort->flush();
}
void SerialPortTool::onMainChannelVGA()
{
serialPort->write(cmdMap.value(MainChannelVGA));
serialPort->flush();
}
void SerialPortTool::onSecondaryChannelHDMI()
{
serialPort->write(cmdMap.value(SecondaryChannelHDMI));
serialPort->flush();
}
void SerialPortTool::onSecondaryChannelVGA()
{
serialPort->write(cmdMap.value(SecondaryChanneVGA));
serialPort->flush();
}

View File

@ -14,6 +14,7 @@ public:
void open(); void open();
void close(); void close();
public slots: public slots:
void onReset();
void onPlaybackStart(); void onPlaybackStart();
void onPlaybackEnd(); void onPlaybackEnd();
void onRecordStart(); void onRecordStart();
@ -32,6 +33,10 @@ public slots:
void onMainChannelOff(); void onMainChannelOff();
void onSecondaryChannelOn(); void onSecondaryChannelOn();
void onSecondaryChannelOff(); void onSecondaryChannelOff();
void onMainChannelHDMI();
void onMainChannelVGA();
void onSecondaryChannelHDMI();
void onSecondaryChannelVGA();
private slots: private slots:
void onSerialError(QSerialPort::SerialPortError error); void onSerialError(QSerialPort::SerialPortError error);
@ -46,9 +51,11 @@ signals:
void btnNextClicked(); void btnNextClicked();
void btnForwardClicked(); void btnForwardClicked();
void btnDoneClicked(); void btnDoneClicked();
void btnChannelSettingClicked();
private: private:
enum CommandType { enum CommandType {
Reset,
PlaybackStart, PlaybackStart,
PlaybackEnd, PlaybackEnd,
RecordStart, RecordStart,
@ -66,7 +73,11 @@ private:
MainChannelOn, MainChannelOn,
MainChannelOff, MainChannelOff,
SecondaryChannelOff, SecondaryChannelOff,
SecondaryChannelOn SecondaryChannelOn,
MainChannelHDMI,
MainChannelVGA,
SecondaryChannelHDMI,
SecondaryChanneVGA
}; };
QSerialPort* serialPort; // 串口 QSerialPort* serialPort; // 串口

View File

@ -62,7 +62,7 @@ void TcpRequestHandler::setIpaddr(TcpRequest* request, TcpResponse* reponse)
netMap["gateway"] = params.value("gateway"); netMap["gateway"] = params.value("gateway");
Json::saveFile(netMap, Constant::NetConfigPath); Json::saveFile(netMap, Constant::NetConfigPath);
reponse->success(); reponse->success("修改ip地址成功请重新连接");
Tool::writeCom(Constant::NetScriptPath); Tool::writeCom(Constant::NetScriptPath);
} }
@ -81,7 +81,7 @@ void TcpRequestHandler::setName(TcpRequest* request, TcpResponse* reponse)
QVariantMap cfg = Json::loadFile(Constant::ConfigurationPath).toMap(); QVariantMap cfg = Json::loadFile(Constant::ConfigurationPath).toMap();
cfg["name"] = params.value("name"); cfg["name"] = params.value("name");
Json::saveFile(cfg, Constant::ConfigurationPath); Json::saveFile(cfg, Constant::ConfigurationPath);
reponse->success(); reponse->success("设置名称成功");
} }
/** /**
@ -92,7 +92,7 @@ void TcpRequestHandler::getName(TcpRequest* request, TcpResponse* reponse)
QVariantMap config = Json::loadFile(Constant::ConfigurationPath).toMap(); QVariantMap config = Json::loadFile(Constant::ConfigurationPath).toMap();
QString name = config["name"].toString(); QString name = config["name"].toString();
QString data = QString("url=get_name\r\nstatus=success\r\nname=%1").arg(name); QString data = QString("url=get_name\r\nstatus=success\r\nname=%1").arg(name);
reponse->success("", name); reponse->success("获取盒子名称成功", name);
} }
/** /**
@ -190,12 +190,10 @@ void TcpRequestHandler::getFileList(TcpRequest* request, TcpResponse* reponse)
QString videoPath = QString("%1/%2").arg(Constant::VideoPath).arg(interface); QString videoPath = QString("%1/%2").arg(Constant::VideoPath).arg(interface);
QStringList videoList = Tool::getFileList(videoPath); QStringList videoList = Tool::getFileList(videoPath);
// 如果最后一个文件名是当前正在录制的文件名,则去除
// 复制两份测试用 if (videoList.last() == Channel::curRecordFilename) {
QStringList copy = videoList; videoList.pop_back();
QStringList copy1 = videoList; }
videoList.append(copy);
videoList.append(copy1);
reponse->success("获取文件成功", videoList); reponse->success("获取文件成功", videoList);
} }
@ -284,7 +282,8 @@ void TcpRequestHandler::setPlaybackMode(TcpRequest* request, TcpResponse* repons
} }
QVariantMap cfg = Json::loadFile(Constant::ConfigurationPath).toMap(); QVariantMap cfg = Json::loadFile(Constant::ConfigurationPath).toMap();
int mode = cfg["playbackMode"].toInt();; int mode = cfg["playbackMode"].toInt();
;
if (playbackMode == mode) { if (playbackMode == mode) {
Log::info("record mode has not changed, there is nothing need to do"); Log::info("record mode has not changed, there is nothing need to do");
reponse->success("回放参数无需改变"); reponse->success("回放参数无需改变");

View File

@ -29,7 +29,6 @@ QStringList Tool::getFileList(QString path)
nameFilters << "*.mp4"; nameFilters << "*.mp4";
dir.setNameFilters(nameFilters); dir.setNameFilters(nameFilters);
fileList = dir.entryList(); fileList = dir.entryList();
return fileList; return fileList;
} }
@ -101,9 +100,9 @@ int64_t Tool::getAvailableStorage(QString mountedPath)
continue; continue;
index += 1; index += 1;
if (index == 2) if (index == 2)
used = s.toInt(); used = s.toLong();
else if (index == 3) else if (index == 3)
available = s.toInt(); available = s.toLong();
} }
qDebug() << QString("%1: used %2 bytes, available %3 bytes") qDebug() << QString("%1: used %2 bytes, available %3 bytes")
.arg(mountedPath) .arg(mountedPath)

View File

@ -35,7 +35,8 @@ Widget::Widget(QWidget* parent)
progressBar = new ProgressBar(this); progressBar = new ProgressBar(this);
progressBar->hide(); progressBar->hide();
message = new Message(this); channelSetting = new ChannelSetting(this);
channelSetting->hide();
// 设置窗体背景透明 // 设置窗体背景透明
QPalette pal = palette(); QPalette pal = palette();
@ -63,19 +64,23 @@ Widget::Widget(QWidget* parent)
bool available = data["avalible"].toBool(); bool available = data["avalible"].toBool();
if (available) { if (available) {
Log::info("video input {} is available", Log::info("video input {} is available",
chn->channelName == Constant::MainChannel ? "HDMI-A" : "HDMI-B"); chn->channelName == Constant::MainChannel ? "HDMI-C" : "HDMI-D");
if (chn->channelName == Constant::MainChannel) { if (chn->channelName == Constant::MainChannel) {
serialPortTool->onMainChannelOn(); serialPortTool->onMainChannelOn();
QThread::msleep(100);
} else { } else {
serialPortTool->onSecondaryChannelOn(); serialPortTool->onSecondaryChannelOn();
QThread::msleep(100);
} }
} else { } else {
Log::info("video input {} is not available", Log::info("video input {} is not available",
chn->channelName == Constant::MainChannel ? "HDMI-A" : "HDMI-B"); chn->channelName == Constant::MainChannel ? "HDMI-C" : "HDMI-D");
if (chn->channelName == Constant::MainChannel) { if (chn->channelName == Constant::MainChannel) {
serialPortTool->onMainChannelOff(); serialPortTool->onMainChannelOff();
QThread::msleep(100);
} else { } else {
serialPortTool->onSecondaryChannelOff(); serialPortTool->onSecondaryChannelOff();
QThread::msleep(100);
} }
} }
} }
@ -84,12 +89,13 @@ Widget::Widget(QWidget* parent)
connect(serialPortTool, SIGNAL(btnPlaybackClicked()), this, SLOT(onBtnPlaybackClicked())); connect(serialPortTool, SIGNAL(btnPlaybackClicked()), this, SLOT(onBtnPlaybackClicked()));
connect(serialPortTool, SIGNAL(btnPreviousClicked()), this, SLOT(onBtnPreviousClicked())); connect(serialPortTool, SIGNAL(btnPreviousClicked()), this, SLOT(onBtnPreviousClicked()));
connect(serialPortTool, SIGNAL(btnPauseClicked()), this, SLOT(onBtnEnterClicked())); connect(serialPortTool, SIGNAL(btnPauseClicked()), this, SLOT(onBtnPasueClicked()));
connect(serialPortTool, SIGNAL(btnReturnClicked()), this, SLOT(onBtnReturnClicked())); connect(serialPortTool, SIGNAL(btnReturnClicked()), this, SLOT(onBtnReturnClicked()));
connect(serialPortTool, SIGNAL(btnBackClicked()), this, SLOT(onBtnBackClicked())); connect(serialPortTool, SIGNAL(btnBackClicked()), this, SLOT(onBtnBackClicked()));
connect(serialPortTool, SIGNAL(btnNextClicked()), this, SLOT(onBtnNextClicked())); connect(serialPortTool, SIGNAL(btnNextClicked()), this, SLOT(onBtnNextClicked()));
connect(serialPortTool, SIGNAL(btnForwardClicked()), this, SLOT(onBtnForwardClicked())); connect(serialPortTool, SIGNAL(btnForwardClicked()), this, SLOT(onBtnForwardClicked()));
connect(serialPortTool, SIGNAL(btnDoneClicked()), this, SLOT(onBtnEnterClicked())); connect(serialPortTool, SIGNAL(btnDoneClicked()), this, SLOT(onBtnEnterClicked()));
connect(serialPortTool, SIGNAL(btnChannelSettingClicked()), this, SLOT(onBtnChannelSettingClicked()));
} }
Widget::~Widget() Widget::~Widget()
@ -98,7 +104,46 @@ Widget::~Widget()
delete progressTimer; delete progressTimer;
delete menu; delete menu;
delete progressBar; delete progressBar;
delete message; delete channelSetting;
}
void Widget::renderList()
{
ui->listWidget->clear();
if (fileList.isEmpty()) {
ui->listWidget->show();
return;
}
// 如果在录制中应该出去正在录制的文件名
if (fileList.last() == Channel::curRecordFilename) {
fileList.pop_back();
}
QListWidgetItem* curItem = nullptr;
for (QString& file : fileList) {
QListWidgetItem* item = new QListWidgetItem(file);
ui->listWidget->addItem(item);
if (isPlayback) {
// 一路回放
if (playbackMode == Constant::OneChannelPlayback) {
if (curPlayChannel == curSelectChannel && item->text() == curPlayFilename) {
curItem = item;
}
}
// 两路回放
else {
if (item->text() == curPlayFilename) {
curItem = item;
}
}
}
}
ui->listWidget->show();
if (curItem) {
ui->listWidget->setCurrentItem(curItem);
} else {
ui->listWidget->setCurrentRow(0);
}
} }
/** /**
@ -107,15 +152,8 @@ Widget::~Widget()
void Widget::showPlayList() void Widget::showPlayList()
{ {
QString dirPath = QString("%1/%2").arg(Constant::VideoPath).arg(curSelectChannel); QString dirPath = QString("%1/%2").arg(Constant::VideoPath).arg(curSelectChannel);
QStringList files = Tool::getFileList(dirPath); fileList = Tool::getFileList(dirPath);
renderList();
ui->listWidget->clear();
for (QString& file : files) {
QListWidgetItem* item = new QListWidgetItem(file);
ui->listWidget->addItem(item);
}
ui->listWidget->show();
ui->listWidget->setCurrentRow(0);
} }
/** /**
@ -133,6 +171,9 @@ void Widget::onProgressTimeout()
*/ */
void Widget::onBtnPlaybackClicked() void Widget::onBtnPlaybackClicked()
{ {
// 如果在进行通道设置屏蔽回放操作
if (channelSetting->isVisible())
return;
Log::info("receive command playback, playback mode: {}", playbackMode); Log::info("receive command playback, playback mode: {}", playbackMode);
// 如果是一路回放,显示选择菜单 // 如果是一路回放,显示选择菜单
if (playbackMode == Constant::OneChannelPlayback) { if (playbackMode == Constant::OneChannelPlayback) {
@ -147,10 +188,15 @@ void Widget::onBtnPlaybackClicked()
} }
/** /**
* @brief * @brief ,
* : ==> ==>
*/ */
void Widget::onBtnPreviousClicked() void Widget::onBtnPreviousClicked()
{ {
if (channelSetting->isVisible()) {
channelSetting->onReceivePre();
return;
}
// 菜单显示则切换菜单选中 // 菜单显示则切换菜单选中
if (menu->isVisible()) { if (menu->isVisible()) {
menu->setCurChannel(Constant::MainChannel); menu->setCurChannel(Constant::MainChannel);
@ -168,9 +214,14 @@ void Widget::onBtnPreviousClicked()
/** /**
* @brief * @brief
* : ==> ==>
*/ */
void Widget::onBtnNextClicked() void Widget::onBtnNextClicked()
{ {
if (channelSetting->isVisible()) {
channelSetting->onReceiveNext();
return;
}
if (menu->isVisible()) { if (menu->isVisible()) {
menu->setCurChannel(Constant::SecondaryChannel); menu->setCurChannel(Constant::SecondaryChannel);
return; return;
@ -204,7 +255,7 @@ void Widget::onBtnPasueClicked()
} else { } else {
progressBar->setState(ProgressBar::Play); progressBar->setState(ProgressBar::Play);
// 关闭暂停灯 // 关闭暂停灯
serialPortTool->onPlayPause(); serialPortTool->onPlayResume();
} }
} }
} }
@ -213,9 +264,14 @@ void Widget::onBtnPasueClicked()
/** /**
* @brief * @brief
* ==> ==>
*/ */
void Widget::onBtnEnterClicked() void Widget::onBtnEnterClicked()
{ {
if (channelSetting->isVisible()) {
channelSetting->onReceiveEnter();
return;
}
// 菜单显示,则关闭菜单显示列表 // 菜单显示,则关闭菜单显示列表
if (menu->isVisible()) { if (menu->isVisible()) {
curSelectChannel = menu->getCurChannel(); curSelectChannel = menu->getCurChannel();
@ -237,10 +293,14 @@ void Widget::onBtnEnterClicked()
/** /**
* @brief * @brief
* : ==> ==> * : ==> ==> ==>
*/ */
void Widget::onBtnReturnClicked() void Widget::onBtnReturnClicked()
{ {
if (channelSetting->isVisible()) {
channelSetting->hide();
return;
}
if (menu->isVisible()) { if (menu->isVisible()) {
menu->hide(); menu->hide();
return; return;
@ -255,6 +315,7 @@ void Widget::onBtnReturnClicked()
if (chn->state != Channel::Stop) { if (chn->state != Channel::Stop) {
chn->startPlayLive(); chn->startPlayLive();
serialPortTool->onPlaybackEnd(); serialPortTool->onPlaybackEnd();
curPlayFilename = "";
} }
} }
progressBar->hide(); progressBar->hide();
@ -302,6 +363,20 @@ void Widget::onBtnBackClicked()
seek("back"); seek("back");
} }
/**
* @brief HDMI or VGA
*/
void Widget::onBtnChannelSettingClicked()
{
// 关闭通道选择菜单
if (menu->isVisible())
menu->hide();
// 打开通道设置菜单
if (channelSetting->isVisible())
return;
channelSetting->show();
}
/** /**
* @brief HDMI-OUT0口输出 * @brief HDMI-OUT0口输出
*/ */
@ -349,7 +424,7 @@ void Widget::playOneChannel()
} }
/** /**
* @brief HDMI-A口的视频为主分别从HDMI-OUT0和HDMI-OUT1输出 * @brief HDMI-OUT0和HDMI-OUT1输出
*/ */
void Widget::playTwoChannels() void Widget::playTwoChannels()
{ {
@ -389,7 +464,7 @@ void Widget::playTwoChannels()
condition.wakeAll(); condition.wakeAll();
mutex.unlock(); mutex.unlock();
// 将HDMI-A通道的视频列表作为主列表 // 将通道的视频列表作为主列表
QString dirPath = QString("%1/%2").arg(Constant::VideoPath).arg(Constant::MainChannel); QString dirPath = QString("%1/%2").arg(Constant::VideoPath).arg(Constant::MainChannel);
fileList = Tool::getFileList(dirPath); fileList = Tool::getFileList(dirPath);
} }
@ -410,11 +485,14 @@ void Widget::onPlayEnd()
} }
} }
} }
bool needRefresh = false;
// 计算下一个文件名 // 计算下一个文件名
int index = fileList.indexOf(curPlayFilename); int index = fileList.indexOf(curPlayFilename);
if (index == fileList.length() - 1) { if (index == fileList.length() - 1) {
// 重新刷新文件列表
QString dirPath = QString("%1/%2").arg(Constant::VideoPath).arg(curPlayChannel); QString dirPath = QString("%1/%2").arg(Constant::VideoPath).arg(curPlayChannel);
fileList = Tool::getFileList(dirPath); fileList = Tool::getFileList(dirPath);
// 刷新文件列表后还是最后一个文件
if (index == fileList.length() - 1) { if (index == fileList.length() - 1) {
Log::info("there is no file to play"); Log::info("there is no file to play");
// 显示播放完毕的信息 // 显示播放完毕的信息
@ -429,6 +507,7 @@ void Widget::onPlayEnd()
} }
return; return;
} }
needRefresh = true;
Log::info("refresh current play file list"); Log::info("refresh current play file list");
} }
curPlayFilename = fileList.at(index + 1); curPlayFilename = fileList.at(index + 1);
@ -464,6 +543,11 @@ void Widget::onPlayEnd()
} }
} }
} }
if (needRefresh) {
renderList();
} else {
ui->listWidget->setCurrentRow(ui->listWidget->currentRow() + 1);
}
mutex.lock(); mutex.lock();
curFilename = curPlayFilename; curFilename = curPlayFilename;

View File

@ -2,6 +2,7 @@
#define WIDG_H #define WIDG_H
#include "Channel.h" #include "Channel.h"
#include "ChannelSetting.h"
#include "Menu.h" #include "Menu.h"
#include "Message.h" #include "Message.h"
#include "ProgressBar.h" #include "ProgressBar.h"
@ -27,7 +28,6 @@ private slots:
void onProgressTimeout(); void onProgressTimeout();
void onPlayEnd(); void onPlayEnd();
void onShowRecordLabel(bool show); void onShowRecordLabel(bool show);
void onBtnPlaybackClicked(); void onBtnPlaybackClicked();
void onBtnPreviousClicked(); void onBtnPreviousClicked();
void onBtnNextClicked(); void onBtnNextClicked();
@ -36,6 +36,7 @@ private slots:
void onBtnReturnClicked(); void onBtnReturnClicked();
void onBtnForwardClicked(); void onBtnForwardClicked();
void onBtnBackClicked(); void onBtnBackClicked();
void onBtnChannelSettingClicked();
private: private:
Ui::Widget* ui; Ui::Widget* ui;
@ -49,13 +50,14 @@ private:
Menu* menu; Menu* menu;
ProgressBar* progressBar; ProgressBar* progressBar;
Message* message; ChannelSetting* channelSetting;
private: private:
void seek(QString type); void seek(QString type);
void playOneChannel(); void playOneChannel();
void playTwoChannels(); void playTwoChannels();
Channel* findChannelByName(QString name); Channel* findChannelByName(QString name);
void renderList();
}; };
#endif // WIDG_H #endif // WIDG_H

View File

@ -9,6 +9,7 @@
#include "Tool.h" #include "Tool.h"
#include "Widget.h" #include "Widget.h"
#include <QApplication> #include <QApplication>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
// Tcp服务器 // Tcp服务器
@ -41,6 +42,7 @@ bool loadConfiguration(QString path)
recordMode = Constant::RecordMode(config["recordMode"].toInt()); recordMode = Constant::RecordMode(config["recordMode"].toInt());
playbackMode = Constant::PlaybackMode(config["playbackMode"].toInt()); playbackMode = Constant::PlaybackMode(config["playbackMode"].toInt());
QVariantList list = config["interface"].toList(); QVariantList list = config["interface"].toList();
// 初始化通道
for (int i = 0; i < list.count(); i++) { for (int i = 0; i < list.count(); i++) {
Channel* chn = new Channel(); Channel* chn = new Channel();
QVariantMap cfg = list.at(i).toMap(); QVariantMap cfg = list.at(i).toMap();
@ -60,6 +62,15 @@ bool loadConfiguration(QString path)
return true; return true;
} }
/**
* @brief
*/
void resetLight()
{
printf("reset all lights");
serialPortTool->onReset();
}
/** /**
* @brief * @brief
*/ */
@ -69,16 +80,19 @@ void startRecord()
QString info = Tool::writeCom(QString("df %1").arg(Constant::MountedPath)); QString info = Tool::writeCom(QString("df %1").arg(Constant::MountedPath));
if (!info.contains(Constant::MountedPath)) { if (!info.contains(Constant::MountedPath)) {
Log::error("there is no disk mounted"); Log::error("there is no disk mounted");
serialPortTool->onLoopOn();
QThread::msleep(100);
return; return;
} }
// 一路录制,只录制HDMI-A通道 // 一路录制,只录制通道
if (recordMode == Constant::OneChannelRecord) { if (recordMode == Constant::OneChannelRecord) {
for (Channel* chn : channelList) { for (Channel* chn : channelList) {
if (chn->channelName == Constant::MainChannel) { if (chn->channelName == Constant::MainChannel) {
chn->startRecord(); chn->startRecord();
// 打开录制灯,关闭环路灯 QThread::msleep(100);
serialPortTool->onRecordStart(); serialPortTool->onRecordStart();
QThread::msleep(100);
serialPortTool->onLoopOff(); serialPortTool->onLoopOff();
} }
} }
@ -87,20 +101,24 @@ void startRecord()
else if (recordMode == Constant::TwoChannelRecord) { else if (recordMode == Constant::TwoChannelRecord) {
for (Channel* chn : channelList) { for (Channel* chn : channelList) {
chn->startRecord(); chn->startRecord();
// 打开录制灯,关闭环路灯
serialPortTool->onRecordStart(); serialPortTool->onRecordStart();
QThread::msleep(100);
serialPortTool->onLoopOff(); serialPortTool->onLoopOff();
QThread::msleep(100);
} }
} }
// 无录制 // 无录制
else { else {
qDebug() << "no record";
// 打开环路灯 // 打开环路灯
serialPortTool->onLoopOn(); serialPortTool->onLoopOn();
QThread::msleep(100);
} }
} }
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
// std::atexit(resetLight);
// 初始化日志 // 初始化日志
Log::init(); Log::init();
@ -163,23 +181,21 @@ int main(int argc, char* argv[])
return 0; return 0;
} }
// 串口 // 打开串口
serialPortTool = new SerialPortTool(); serialPortTool = new SerialPortTool();
serialPortTool->open(); serialPortTool->open();
// 打开电源灯
serialPortTool->onPowerOn();
// qt界面 serialPortTool->onPowerOn(); // 打开电源灯
Widget w; QThread::msleep(100);
w.show();
// 开始录制
startRecord();
// 开启Tcp服务 // 开启Tcp服务
server = new TcpServer(); server = new TcpServer();
server->listen(); server->listen();
// qt界面
Widget w;
w.show();
// 硬盘检测线程,检测硬盘容量 // 硬盘检测线程,检测硬盘容量
CheckStorageThread* thread = new CheckStorageThread(); CheckStorageThread* thread = new CheckStorageThread();
thread->start(); thread->start();
@ -187,5 +203,7 @@ int main(int argc, char* argv[])
QObject::connect(thread, SIGNAL(diskNotFull()), serialPortTool, SLOT(onDiskNotFull())); QObject::connect(thread, SIGNAL(diskNotFull()), serialPortTool, SLOT(onDiskNotFull()));
Log::info("start storage check thread..."); Log::info("start storage check thread...");
// 开始录制
startRecord();
return a.exec(); return a.exec();
} }