diff --git a/Channel.cpp b/Channel.cpp index e426ecf..f8b247f 100755 --- a/Channel.cpp +++ b/Channel.cpp @@ -5,17 +5,22 @@ #include "Log.h" #include "Tool.h" #include +#include #include #include #include #include -#include - 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); } /** diff --git a/Channel.h b/Channel.h index 15b11ea..503dd58 100755 --- a/Channel.h +++ b/Channel.h @@ -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(); diff --git a/Constant.h b/Constant.h index 4b7206c..adb7a5e 100755 --- a/Constant.h +++ b/Constant.h @@ -3,7 +3,7 @@ class Constant { public: - Constant() {} + Constant() { } enum RecordMode { NoChannelRecord, OneChannelRecord, @@ -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"; diff --git a/DatabaseManager.cpp b/DatabaseManager.cpp index 5cc7a28..8a6a3fb 100755 --- a/DatabaseManager.cpp +++ b/DatabaseManager.cpp @@ -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; } } diff --git a/Menu.cpp b/Menu.cpp index 3c4a4e0..2a51c61 100755 --- a/Menu.cpp +++ b/Menu.cpp @@ -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(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 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 btns = ui->scrollArea->findChildren(); for (QPushButton* btn : btns) { - if (btn->text() == str) { + if (btn->property("name").toString() == filename) { btn->setChecked(true); + btn->setFocus(); } } } @@ -365,3 +391,36 @@ QList 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; +} \ No newline at end of file diff --git a/Menu.h b/Menu.h index 82be039..d8c120a 100755 --- a/Menu.h +++ b/Menu.h @@ -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 contentList; DatabaseManager* db; - DatabaseManager::Channel currentChannel; - QString currentFilename; + QString curPlayFilename; // 当前正在回放的文件名 + bool channelSelectVisible = false; // 是否显示通道选择,单通道回放显示、双通道不显示 + + DatabaseManager::Channel curSelectChannel; // 当前选择的通道 + DatabaseManager::Channel curPlayChannel; // 当前回放的通道 private: void getContents(); diff --git a/Message.cpp b/Message.cpp deleted file mode 100755 index bdbd8dd..0000000 --- a/Message.cpp +++ /dev/null @@ -1,123 +0,0 @@ -#include "Message.h" -#include -#include -#include - -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(this->layout()); - if (count >= maxCount) { - // remove first - QPair 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 pair(btn, timer); - contentList.append(pair); - count += 1; - - connect(timer, &QTimer::timeout, [=] { - for (int i = 0; i < contentList.length(); i++) { - QPair 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; -} diff --git a/Message.h b/Message.h deleted file mode 100755 index 6e03df3..0000000 --- a/Message.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef MESSAGE_H -#define MESSAGE_H - -#include -#include -#include -#include -#include - -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> contentList; - - QString btnStyle; - -private: - void showMessage(QString content, int duration, Level level); - QPushButton* generateButton(QString content, Level level); -}; - -#endif // MESSAGE_H diff --git a/ProgressBar.h b/ProgressBar.h index 70991b0..992dcbf 100755 --- a/ProgressBar.h +++ b/ProgressBar.h @@ -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; } diff --git a/RecordControlApplication.pro b/RecordControlApplication.pro index fecb16e..6024e31 100755 --- a/RecordControlApplication.pro +++ b/RecordControlApplication.pro @@ -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 \ diff --git a/SerialPortTool.cpp b/SerialPortTool.cpp index 0abea12..87d0ddd 100644 --- a/SerialPortTool.cpp +++ b/SerialPortTool.cpp @@ -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)); diff --git a/SerialPortTool.h b/SerialPortTool.h index 9b73989..59db559 100644 --- a/SerialPortTool.h +++ b/SerialPortTool.h @@ -51,6 +51,8 @@ signals: void btnRightClicked(); void btnConfirmClicked(); void btnReturnClicked(); + void btnVolumnUpClicked(); + void btnVolumnDownClicked(); private: enum CommandType { diff --git a/TcpConnectionHandler.cpp b/TcpConnectionHandler.cpp index e938d9b..7b45695 100644 --- a/TcpConnectionHandler.cpp +++ b/TcpConnectionHandler.cpp @@ -23,6 +23,7 @@ void TcpConnectionHandler::onReadyRead() { bool ret = request->readFromSocket(socket); if (!ret) { + response->setUrl("Unkown Url"); response->error(request->getErrorString()); return; } diff --git a/TcpRequestHandler.cpp b/TcpRequestHandler.cpp index b297c01..6485ecc 100755 --- a/TcpRequestHandler.cpp +++ b/TcpRequestHandler.cpp @@ -5,6 +5,7 @@ #include "Json.h" #include "Log.h" #include "Tool.h" +#include #include #include @@ -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 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()) { - video.remove(); - Log::info("remove video {}", filePath.toStdString()); - reponse->success("删除成功"); + // 删除数据库记录 + 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()) { diff --git a/Tool.cpp b/Tool.cpp index c1cba9f..e1c2cf3 100755 --- a/Tool.cpp +++ b/Tool.cpp @@ -1,4 +1,5 @@ #include "Tool.h" +#include "QTimer" #include #include #include @@ -136,4 +137,4 @@ double Tool::getCostTime(std::function callback, const char* callbac double time = (double)mstimer.nsecsElapsed() / (double)1000000; qDebug() << callbackName << "cast time:" << time << "ms"; return time; -} +} \ No newline at end of file diff --git a/Widget.cpp b/Widget.cpp index 40b8f6d..2517dc6 100755 --- a/Widget.cpp +++ b/Widget.cpp @@ -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(sender()); diff --git a/Widget.h b/Widget.h index fdc04ec..56bbd34 100755 --- a/Widget.h +++ b/Widget.h @@ -3,7 +3,6 @@ #include "Channel.h" #include "Menu.h" -#include "Message.h" #include "ProgressBar.h" #include #include @@ -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: diff --git a/main.cpp b/main.cpp index a954377..f5f58c6 100755 --- a/main.cpp +++ b/main.cpp @@ -15,7 +15,7 @@ #include // Tcp服务器 -TcpServer* server; +TcpServer* server; // 串口工具 SerialPortTool* serialPortTool; // 数据库管理 @@ -23,6 +23,8 @@ DatabaseManager* db; // 视频输出通道 LinkObject* vo; LinkObject* vo1; +// 硬盘检测现场 +CheckStorageThread* thread; // 通道列表 QList channelList; @@ -86,7 +88,7 @@ void startRecord() QThread::msleep(100); return; } - + // 一路录制,只录制主通道 if (recordMode == Constant::OneChannelRecord) { for (Channel* chn : 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()));