RecordControlApplication/Widget.cpp

506 lines
15 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();
message = new Message(this);
// 设置窗体背景透明
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-A" : "HDMI-B");
if (chn->channelName == Constant::MainChannel) {
serialPortTool->onMainChannelOn();
} else {
serialPortTool->onSecondaryChannelOn();
}
} else {
Log::info("video input {} is not available",
chn->channelName == Constant::MainChannel ? "HDMI-A" : "HDMI-B");
if (chn->channelName == Constant::MainChannel) {
serialPortTool->onMainChannelOff();
} else {
serialPortTool->onSecondaryChannelOff();
}
}
}
});
}
connect(serialPortTool, SIGNAL(btnPlaybackClicked()), this, SLOT(onBtnPlaybackClicked()));
connect(serialPortTool, SIGNAL(btnPreviousClicked()), this, SLOT(onBtnPreviousClicked()));
connect(serialPortTool, SIGNAL(btnPauseClicked()), this, SLOT(onBtnEnterClicked()));
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()));
}
Widget::~Widget()
{
delete ui;
delete progressTimer;
delete menu;
delete progressBar;
delete message;
}
/**
* @brief 获取视频文件列表并显示
*/
void Widget::showPlayList()
{
QString dirPath = QString("%1/%2").arg(Constant::VideoPath).arg(curSelectChannel);
QStringList files = Tool::getFileList(dirPath);
ui->listWidget->clear();
for (QString& file : files) {
QListWidgetItem* item = new QListWidgetItem(file);
ui->listWidget->addItem(item);
}
ui->listWidget->show();
ui->listWidget->setCurrentRow(0);
}
/**
* @brief 更新进度条
*/
void Widget::onProgressTimeout()
{
Channel* chn = findChannelByName(Constant::MainChannel);
int pos = chn->file->invoke("getPosition").toInt() / 1000;
progressBar->setCurrent(pos);
}
/**
* @brief 收到回放指令
*/
void Widget::onBtnPlaybackClicked()
{
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 (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 (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->onPlayPause();
}
}
}
}
}
/**
* @brief 收到确定指令
*/
void Widget::onBtnEnterClicked()
{
// 菜单显示,则关闭菜单显示列表
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 (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();
}
}
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-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-A口的视频为主分别从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();
// 将HDMI-A通道的视频列表作为主列表
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;
}
}
}
}
// 计算下一个文件名
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;
}
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();
}
}
}
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;
}