RecordControlApplication/Widget.cpp

590 lines
17 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "Widget.h"
#include "Channel.h"
#include "Constant.h"
#include "Json.h"
#include "Log.h"
#include "SerialPortTool.h"
#include "TcpServer.h"
#include "Tool.h"
#include "ui_Widget.h"
#include <QDir>
#include <QMutex>
#include <QScrollBar>
#include <QWaitCondition>
// 多线程中使用
QMutex mutex;
QWaitCondition condition;
QString curFilename;
extern QList<Channel*> channelList;
extern Constant::PlaybackMode playbackMode;
extern SerialPortTool* serialPortTool;
Widget::Widget(QWidget* parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->lblA->setPixmap(QPixmap(":/images/no-record.png"));
ui->lblB->setPixmap(QPixmap(":/images/no-record.png"));
menu = new Menu(this);
menu->hide();
progressBar = new ProgressBar(this);
progressBar->hide();
channelSetting = new ChannelSetting(this);
channelSetting->hide();
// 设置窗体背景透明
QPalette pal = palette();
pal.setBrush(QPalette::Base, Qt::transparent);
setPalette(pal);
setAttribute(Qt::WA_TranslucentBackground, true);
// 设置listwidget无滚动条
ui->listWidget->horizontalScrollBar()->hide();
ui->listWidget->verticalScrollBar()->hide();
ui->listWidget->hide();
// 每5秒更新一次进度条
progressTimer = new QTimer();
progressTimer->setInterval(500);
connect(progressTimer, SIGNAL(timeout()), this, SLOT(onProgressTimeout()));
for (Channel* chn : channelList) {
connect(chn, SIGNAL(playEnd()), this, SLOT(onPlayEnd()));
connect(chn, SIGNAL(showRecordState(bool)), this, SLOT(onShowRecordLabel(bool)));
// 监听输入信号的变化
connect(chn->videoInput, &LinkObject::newEvent, [=](QString type, QVariant msg) {
if (type == "signal") {
QVariantMap data = msg.toMap();
bool available = data["avalible"].toBool();
if (available) {
Log::info("video input {} is available",
chn->channelName == Constant::MainChannel ? "HDMI-C" : "HDMI-D");
if (chn->channelName == Constant::MainChannel) {
serialPortTool->onMainChannelOn();
QThread::msleep(100);
} else {
serialPortTool->onSecondaryChannelOn();
QThread::msleep(100);
}
} else {
Log::info("video input {} is not available",
chn->channelName == Constant::MainChannel ? "HDMI-C" : "HDMI-D");
if (chn->channelName == Constant::MainChannel) {
serialPortTool->onMainChannelOff();
QThread::msleep(100);
} else {
serialPortTool->onSecondaryChannelOff();
QThread::msleep(100);
}
}
}
});
}
connect(serialPortTool, SIGNAL(btnPlaybackClicked()), this, SLOT(onBtnPlaybackClicked()));
connect(serialPortTool, SIGNAL(btnPreviousClicked()), this, SLOT(onBtnPreviousClicked()));
connect(serialPortTool, SIGNAL(btnPauseClicked()), this, SLOT(onBtnPasueClicked()));
connect(serialPortTool, SIGNAL(btnReturnClicked()), this, SLOT(onBtnReturnClicked()));
connect(serialPortTool, SIGNAL(btnBackClicked()), this, SLOT(onBtnBackClicked()));
connect(serialPortTool, SIGNAL(btnNextClicked()), this, SLOT(onBtnNextClicked()));
connect(serialPortTool, SIGNAL(btnForwardClicked()), this, SLOT(onBtnForwardClicked()));
connect(serialPortTool, SIGNAL(btnDoneClicked()), this, SLOT(onBtnEnterClicked()));
connect(serialPortTool, SIGNAL(btnChannelSettingClicked()), this, SLOT(onBtnChannelSettingClicked()));
}
Widget::~Widget()
{
delete ui;
delete progressTimer;
delete menu;
delete progressBar;
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);
}
}
/**
* @brief 获取视频文件列表并显示
*/
void Widget::showPlayList()
{
QString dirPath = QString("%1/%2").arg(Constant::VideoPath).arg(curSelectChannel);
fileList = Tool::getFileList(dirPath);
renderList();
}
/**
* @brief 更新进度条
*/
void Widget::onProgressTimeout()
{
Channel* chn = findChannelByName(Constant::MainChannel);
int pos = chn->file->invoke("getPosition").toInt() / 1000;
progressBar->setCurrent(pos);
}
/**
* @brief 收到回放指令
*/
void Widget::onBtnPlaybackClicked()
{
// 如果在进行通道设置屏蔽回放操作
if (channelSetting->isVisible())
return;
Log::info("receive command playback, playback mode: {}", playbackMode);
// 如果是一路回放,显示选择菜单
if (playbackMode == Constant::OneChannelPlayback) {
if (!menu->isVisible())
menu->show();
}
// 两路回放不显示菜单,直接显示列表
else if (playbackMode == Constant::TwoChannelPlayback) {
curSelectChannel = Constant::MainChannel;
showPlayList();
}
}
/**
* @brief 收到上段指令, 优先级
* 处理优先级: 通道设置菜单 ==> 通道选择菜单 ==> 列表
*/
void Widget::onBtnPreviousClicked()
{
if (channelSetting->isVisible()) {
channelSetting->onReceivePre();
return;
}
// 菜单显示则切换菜单选中
if (menu->isVisible()) {
menu->setCurChannel(Constant::MainChannel);
return;
}
// 列表显示,则选中上一个视频
if (ui->listWidget->isVisible()) {
int curRow = ui->listWidget->currentRow();
if (curRow == 0)
curRow = ui->listWidget->count();
ui->listWidget->setCurrentRow(curRow - 1);
return;
}
}
/**
* @brief 收到下段指令
* 处理优先级: 通道设置菜单 ==> 通道选择菜单 ==> 列表
*/
void Widget::onBtnNextClicked()
{
if (channelSetting->isVisible()) {
channelSetting->onReceiveNext();
return;
}
if (menu->isVisible()) {
menu->setCurChannel(Constant::SecondaryChannel);
return;
}
if (ui->listWidget->isVisible()) {
int curRow = ui->listWidget->currentRow();
if (curRow == ui->listWidget->count() - 1) {
curRow = -1;
}
ui->listWidget->setCurrentRow(curRow + 1);
return;
}
}
/**
* @brief 收到暂停指令
*/
void Widget::onBtnPasueClicked()
{
if (!isPlayback)
return;
for (Channel* chn : channelList) {
if (chn->state == Channel::Playback || chn->state == Channel::Pause) {
chn->togglePause();
if (chn->channelName == Constant::MainChannel) {
progressBar->showMax();
if (chn->state == Channel::Pause) {
progressBar->setState(ProgressBar::Pause);
// 打开暂停灯
serialPortTool->onPlayPause();
} else {
progressBar->setState(ProgressBar::Play);
// 关闭暂停灯
serialPortTool->onPlayResume();
}
}
}
}
}
/**
* @brief 收到确定指令
* 通道设置菜单 ==> 通道选择菜单 ==> 列表
*/
void Widget::onBtnEnterClicked()
{
if (channelSetting->isVisible()) {
channelSetting->onReceiveEnter();
return;
}
// 菜单显示,则关闭菜单显示列表
if (menu->isVisible()) {
curSelectChannel = menu->getCurChannel();
menu->hide();
showPlayList();
return;
}
if (ui->listWidget->isVisible()) {
if (ui->listWidget->count() == 0)
return;
if (playbackMode == Constant::OneChannelPlayback)
playOneChannel();
else if (playbackMode == Constant::TwoChannelPlayback)
playTwoChannels();
serialPortTool->onPlaybackStart();
return;
}
}
/**
* @brief 收到返回指令
* 处理优先级: 通道设置菜单 ==> 通道选择菜单 ==> 列表 ==> 回放
*/
void Widget::onBtnReturnClicked()
{
if (channelSetting->isVisible()) {
channelSetting->hide();
return;
}
if (menu->isVisible()) {
menu->hide();
return;
}
if (ui->listWidget->isVisible()) {
ui->listWidget->hide();
return;
}
if (isPlayback) {
// 停止回放
for (Channel* chn : channelList) {
if (chn->state != Channel::Stop) {
chn->startPlayLive();
serialPortTool->onPlaybackEnd();
curPlayFilename = "";
}
}
progressBar->hide();
ui->lblA->show();
ui->lblB->show();
}
}
/**
* @brief 视频跳转
*/
void Widget::seek(QString type)
{
if (!isPlayback)
return;
for (Channel* chn : channelList) {
if (chn->state == Channel::Pause || chn->state == Channel::Playback) {
if (type == "forward") {
chn->forward();
serialPortTool->onFoward();
} else {
chn->back();
serialPortTool->onBack();
}
if (chn->channelName == Constant::MainChannel)
progressBar->showMax();
}
}
}
/**
* @brief 快进
*/
void Widget::onBtnForwardClicked()
{
seek("forward");
}
/**
* @brief 快退
*/
void Widget::onBtnBackClicked()
{
seek("back");
}
/**
* @brief 打开通道设置HDMI or VGA
*/
void Widget::onBtnChannelSettingClicked()
{
// 关闭通道选择菜单
if (menu->isVisible())
menu->hide();
// 打开通道设置菜单
if (channelSetting->isVisible())
return;
channelSetting->show();
}
/**
* @brief 一路回放将当前选中播放的视频从HDMI-OUT0口输出
*/
void Widget::playOneChannel()
{
QString filename = ui->listWidget->currentItem()->text();
QString path = QString("%1/%2/%3").arg(Constant::VideoPath).arg(curSelectChannel).arg(filename);
Channel* channel = findChannelByName(Constant::MainChannel);
for (Channel* chn : channelList) {
chn->startPlayLive();
}
bool ret = channel->startPlayback(path);
if (!ret)
progressBar->hide();
isPlayback = true;
curPlayChannel = curSelectChannel;
curPlayFilename = filename;
// 全局保存当前播放的视频
mutex.lock();
curFilename = filename;
condition.wakeAll();
mutex.unlock();
// 保存当前播放视频列表
QString dirPath = QString("%1/%2").arg(Constant::VideoPath).arg(curPlayChannel);
fileList = Tool::getFileList(dirPath);
int duration = channel->playbackDuration;
progressBar->setDuration(duration);
progressBar->setCurrent(0);
progressBar->show();
progressBar->showMax();
progressBar->setState(ProgressBar::Play);
if (progressTimer->isActive()) {
progressTimer->stop();
progressTimer->start();
} else {
progressTimer->start();
}
ui->lblA->hide();
ui->lblB->hide();
}
/**
* @brief 两路回放以主通道的视频为主分别从HDMI-OUT0和HDMI-OUT1输出
*/
void Widget::playTwoChannels()
{
QString filename = ui->listWidget->currentItem()->text();
for (Channel* chn : channelList) {
QString path = QString("%1/%2/%3").arg(Constant::VideoPath).arg(chn->channelName).arg(filename);
int ret = chn->startPlayback(path);
if (chn->channelName == Constant::MainChannel) {
if (ret) {
int duration = chn->playbackDuration;
progressBar->setDuration(duration);
progressBar->setCurrent(0);
progressBar->show();
progressBar->showMax();
progressBar->setState(ProgressBar::Play);
if (progressTimer->isActive()) {
progressTimer->stop();
progressTimer->start();
} else {
progressTimer->start();
}
ui->lblA->hide();
ui->lblB->hide();
} else {
progressBar->hide();
}
}
}
curPlayFilename = filename;
curPlayChannel = Constant::MainChannel;
isPlayback = true;
// 全局保存正在播放的视频
mutex.lock();
curFilename = filename;
condition.wakeAll();
mutex.unlock();
// 将主通道的视频列表作为主列表
QString dirPath = QString("%1/%2").arg(Constant::VideoPath).arg(Constant::MainChannel);
fileList = Tool::getFileList(dirPath);
}
/**
* @brief 当前视频播放完毕
*/
void Widget::onPlayEnd()
{
// 当两路回放时,只处理一次槽函数
if (playbackMode == Constant::TwoChannelPlayback) {
LinkObject* file = static_cast<LinkObject*>(sender());
for (Channel* chn : channelList) {
if (chn->file == file) {
if (chn->channelName != Constant::MainChannel) {
return;
}
}
}
}
bool needRefresh = false;
// 计算下一个文件名
int index = fileList.indexOf(curPlayFilename);
if (index == fileList.length() - 1) {
// 重新刷新文件列表
QString dirPath = QString("%1/%2").arg(Constant::VideoPath).arg(curPlayChannel);
fileList = Tool::getFileList(dirPath);
// 刷新文件列表后还是最后一个文件
if (index == fileList.length() - 1) {
Log::info("there is no file to play");
// 显示播放完毕的信息
if (playbackMode == Constant::OneChannelPlayback) {
Channel* chn = findChannelByName(Constant::MainChannel);
if (chn)
chn->showFinishPromot();
} else if (playbackMode == Constant::TwoChannelPlayback) {
for (Channel* chn : channelList) {
chn->showFinishPromot();
}
}
return;
}
needRefresh = true;
Log::info("refresh current play file list");
}
curPlayFilename = fileList.at(index + 1);
// 播放下一个视频
if (playbackMode == Constant::OneChannelPlayback) {
Channel* chn = findChannelByName(Constant::MainChannel);
if (chn) {
QString path = QString("%1/%2/%3").arg(Constant::VideoPath).arg(curPlayChannel).arg(curPlayFilename);
bool ret = chn->startPlayback(path);
if (chn->channelName == Constant::MainChannel) {
if (!ret) {
progressBar->hide();
return;
}
int duration = chn->playbackDuration;
progressBar->setDuration(duration);
progressBar->showMax();
}
}
} else if (playbackMode == Constant::TwoChannelPlayback) {
for (Channel* chn : channelList) {
QString path = QString("%1/%2/%3").arg(Constant::VideoPath).arg(chn->channelName).arg(curPlayFilename);
bool ret = chn->startPlayback(path);
if (chn->channelName == Constant::MainChannel) {
if (!ret) {
progressBar->hide();
continue;
}
int duration = chn->playbackDuration;
progressBar->setDuration(duration);
progressBar->showMax();
}
}
}
if (needRefresh) {
renderList();
} else {
ui->listWidget->setCurrentRow(ui->listWidget->currentRow() + 1);
}
mutex.lock();
curFilename = curPlayFilename;
condition.wakeAll();
mutex.unlock();
}
/**
* @brief 显示录制状态的槽函数
* @param show 是否正在录制
*/
void Widget::onShowRecordLabel(bool show)
{
Channel* chn = static_cast<Channel*>(sender());
QLabel* label;
if (chn->channelName == Constant::MainChannel) {
label = ui->lblA;
} else {
label = ui->lblB;
}
if (show) {
label->setPixmap(QPixmap(":/images/record.png"));
} else
label->setPixmap(QPixmap(":/images/no-record.png"));
}
/**
* @brief 根据名称查找通道
* @param name 通道名称
*/
Channel* Widget::findChannelByName(QString name)
{
for (Channel* chn : channelList) {
if (chn->channelName == name) {
return chn;
}
}
return nullptr;
}