429 lines
12 KiB
C++
Executable File
429 lines
12 KiB
C++
Executable File
#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->lblImgA->setPixmap(QPixmap(":/images/no-record.png"));
|
||
ui->lblImgB->setPixmap(QPixmap(":/images/no-record.png"));
|
||
ui->lblTxtA->setText("未录制");
|
||
ui->lblTxtB->setText("未录制");
|
||
ui->recordWidget->hide();
|
||
|
||
menu = new Menu();
|
||
menu->hide();
|
||
// 设置是否显示通道选择
|
||
menu->setChannelSelectVisible(playbackMode == Constant::OneChannelPlayback);
|
||
ui->progressBar->hide();
|
||
|
||
// 每5秒更新一次进度条
|
||
progressTimer = new QTimer();
|
||
progressTimer->setInterval(200);
|
||
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 ? Constant::MainChannel : Constant::SecondaryChannel);
|
||
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 ? Constant::MainChannel : Constant::SecondaryChannel);
|
||
if (chn->channelName == Constant::MainChannel) {
|
||
serialPortTool->onMainChannelOff();
|
||
QThread::msleep(100);
|
||
} else {
|
||
serialPortTool->onSecondaryChannelOff();
|
||
QThread::msleep(100);
|
||
}
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
connect(serialPortTool, SIGNAL(btnMenuClicked()), this, SLOT(onBtnMenuClicked()));
|
||
connect(serialPortTool, SIGNAL(btnUpClicked()), this, SLOT(onBtnUpClicked()));
|
||
connect(serialPortTool, SIGNAL(btnDownClicked()), this, SLOT(onBtnDownClicked()));
|
||
connect(serialPortTool, SIGNAL(btnLeftClicked()), this, SLOT(onBtnLeftClicked()));
|
||
connect(serialPortTool, SIGNAL(btnRightClicked()), this, SLOT(onBtnRightClicked()));
|
||
connect(serialPortTool, SIGNAL(btnConfirmClicked()), this, SLOT(onBtnConfirmClicked()));
|
||
connect(serialPortTool, SIGNAL(btnReturnClicked()), this, SLOT(onBtnReturnClicked()));
|
||
|
||
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)));
|
||
}
|
||
|
||
Widget::~Widget()
|
||
{
|
||
delete ui;
|
||
delete progressTimer;
|
||
delete menu;
|
||
}
|
||
|
||
/**
|
||
* @brief 更新进度条
|
||
*/
|
||
void Widget::onProgressTimeout()
|
||
{
|
||
Channel* chn = findChannelByName(Constant::MainChannel);
|
||
if (chn) {
|
||
// 获取当前播放位置,单位ms
|
||
int pos = chn->inputFile->invoke("getPosition").toInt();
|
||
ui->progressBar->setCurrent(pos);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 按下菜单按键
|
||
*/
|
||
void Widget::onBtnMenuClicked()
|
||
{
|
||
if (!menu->isVisible()) {
|
||
menu->show();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 按下返回按键。优先级:菜单 > 播放
|
||
*/
|
||
void Widget::onBtnReturnClicked()
|
||
{
|
||
// 关闭菜单
|
||
if (menu->isVisible()) {
|
||
menu->hide();
|
||
return;
|
||
}
|
||
// 关闭回放
|
||
if (isPlayback) {
|
||
// 停止回放
|
||
for (Channel* chn : channelList) {
|
||
if (chn->state != Channel::Stop) {
|
||
chn->startPlayLive();
|
||
serialPortTool->onPlaybackEnd();
|
||
curPlayFilename = "";
|
||
}
|
||
}
|
||
// 隐藏进度条并关闭定时器
|
||
ui->progressBar->hide();
|
||
progressTimer->stop();
|
||
// 显示录制状态
|
||
// ui->recordWidget->show();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 按下上键。优先级: 菜单 > 播放
|
||
*/
|
||
void Widget::onBtnUpClicked()
|
||
{
|
||
if (menu->isVisible()) {
|
||
menu->move(Menu::Up);
|
||
return;
|
||
}
|
||
if (isPlayback) {
|
||
emit needPlayVideo("previous");
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 按下下键。 优先级: 菜单 > 播放
|
||
*/
|
||
void Widget::onBtnDownClicked()
|
||
{
|
||
if (menu->isVisible()) {
|
||
menu->move(Menu::Down);
|
||
return;
|
||
}
|
||
if (isPlayback) {
|
||
emit needPlayVideo("next");
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 按下左键。优先级: 菜单 > 播放。
|
||
*/
|
||
void Widget::onBtnLeftClicked()
|
||
{
|
||
if (menu->isVisible()) {
|
||
menu->move(Menu::Left);
|
||
return;
|
||
}
|
||
if (isPlayback) {
|
||
seek("back");
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 按下左键。优先级: 菜单 > 播放
|
||
*/
|
||
void Widget::onBtnRightClicked()
|
||
{
|
||
if (menu->isVisible()) {
|
||
menu->move(Menu::Right);
|
||
return;
|
||
}
|
||
if (isPlayback) {
|
||
seek("forward");
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 按下ok键。优先级: 菜单 > 回放
|
||
*/
|
||
void Widget::onBtnConfirmClicked()
|
||
{
|
||
if (menu->isVisible()) {
|
||
menu->confirm();
|
||
return;
|
||
}
|
||
if (isPlayback) {
|
||
// 切换暂停和播放
|
||
for (Channel* chn : channelList) {
|
||
if (chn->state == Channel::Playback || chn->state == Channel::Pause) {
|
||
chn->togglePause();
|
||
if (chn->channelName == Constant::MainChannel) {
|
||
ui->progressBar->showMax();
|
||
if (chn->state == Channel::Pause) {
|
||
ui->progressBar->setState(ProgressBar::Pause);
|
||
// 打开暂停灯
|
||
serialPortTool->onPlayPause();
|
||
} else {
|
||
ui->progressBar->setState(ProgressBar::Play);
|
||
// 关闭暂停灯
|
||
serialPortTool->onPlayResume();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 回放视频
|
||
*/
|
||
void Widget::onBtnVideoClicked(QString filename)
|
||
{
|
||
if (filename == "first") {
|
||
// 显示提示弹窗
|
||
} else if (filename == "last") {
|
||
if (playbackMode == Constant::OneChannelPlayback) {
|
||
Channel* chn = findChannelByName(Constant::MainChannel);
|
||
chn->showFinishPromot();
|
||
} else {
|
||
for (Channel* chn : channelList)
|
||
chn->showFinishPromot();
|
||
}
|
||
} else {
|
||
if (playbackMode == Constant::OneChannelPlayback) {
|
||
playOneChannel(filename);
|
||
} else {
|
||
playTwoChannels(filename);
|
||
}
|
||
serialPortTool->onPlaybackStart();
|
||
}
|
||
}
|
||
|
||
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);
|
||
Channel* channel = findChannelByName(Constant::MainChannel);
|
||
for (Channel* chn : channelList) {
|
||
chn->startPlayLive();
|
||
}
|
||
bool ret = channel->startPlayback(path);
|
||
if (!ret) {
|
||
Log::info("play back error");
|
||
ui->progressBar->hide();
|
||
}
|
||
|
||
isPlayback = true;
|
||
curPlayChannel = curSelectChannel;
|
||
curPlayFilename = filename;
|
||
|
||
// 全局保存当前播放的视频
|
||
mutex.lock();
|
||
curFilename = filename;
|
||
condition.wakeAll();
|
||
mutex.unlock();
|
||
|
||
int duration = channel->playbackDuration;
|
||
ui->progressBar->setDuration(duration);
|
||
ui->progressBar->setCurrent(0);
|
||
ui->progressBar->show();
|
||
ui->progressBar->showMax();
|
||
ui->progressBar->setState(ProgressBar::Play);
|
||
|
||
if (progressTimer->isActive()) {
|
||
progressTimer->stop();
|
||
progressTimer->start();
|
||
} else {
|
||
progressTimer->start();
|
||
}
|
||
ui->recordWidget->hide();
|
||
}
|
||
|
||
/**
|
||
* @brief 两路回放,以主通道的视频为主分别从HDMI-OUT0和HDMI-OUT1输出
|
||
*/
|
||
void Widget::playTwoChannels(QString filename)
|
||
{
|
||
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;
|
||
ui->progressBar->setDuration(duration);
|
||
ui->progressBar->setCurrent(0);
|
||
ui->progressBar->show();
|
||
ui->progressBar->showMax();
|
||
ui->progressBar->setState(ProgressBar::Play);
|
||
if (progressTimer->isActive()) {
|
||
progressTimer->stop();
|
||
progressTimer->start();
|
||
} else {
|
||
progressTimer->start();
|
||
}
|
||
ui->recordWidget->hide();
|
||
} else {
|
||
ui->progressBar->hide();
|
||
ui->recordWidget->hide();
|
||
}
|
||
}
|
||
}
|
||
|
||
curPlayFilename = filename;
|
||
curPlayChannel = Constant::MainChannel;
|
||
isPlayback = true;
|
||
|
||
// 全局保存正在播放的视频
|
||
mutex.lock();
|
||
curFilename = filename;
|
||
condition.wakeAll();
|
||
mutex.unlock();
|
||
}
|
||
|
||
/**
|
||
* @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)
|
||
ui->progressBar->showMax();
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 当前视频播放完毕
|
||
*/
|
||
void Widget::onPlayEnd()
|
||
{
|
||
// 当两路回放时,只处理一次槽函数
|
||
if (playbackMode == Constant::TwoChannelPlayback) {
|
||
LinkObject* file = static_cast<LinkObject*>(sender());
|
||
for (Channel* chn : channelList) {
|
||
if (chn->inputFile == file) {
|
||
if (chn->channelName != Constant::MainChannel) {
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
emit needPlayVideo("next");
|
||
}
|
||
|
||
/**
|
||
* @brief 显示录制状态的槽函数
|
||
* @param show 是否正在录制
|
||
*/
|
||
void Widget::onShowRecordLabel(bool show)
|
||
{
|
||
Channel* chn = static_cast<Channel*>(sender());
|
||
QLabel* lblImg;
|
||
QLabel* lblTxt;
|
||
if (chn->channelName == Constant::MainChannel) {
|
||
lblImg = ui->lblImgA;
|
||
lblTxt = ui->lblTxtA;
|
||
} else {
|
||
lblImg = ui->lblImgB;
|
||
lblTxt = ui->lblTxtB;
|
||
}
|
||
if (show) {
|
||
lblImg->setPixmap(QPixmap(":/images/record.png"));
|
||
lblTxt->setText("录制中");
|
||
} else {
|
||
lblImg->setPixmap(QPixmap(":/images/no-record.png"));
|
||
lblTxt->setText("未录制");
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 根据名称查找通道
|
||
* @param name 通道名称
|
||
*/
|
||
Channel* Widget::findChannelByName(QString name)
|
||
{
|
||
for (Channel* chn : channelList) {
|
||
if (chn->channelName == name) {
|
||
return chn;
|
||
}
|
||
}
|
||
return nullptr;
|
||
}
|