#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 #include #include #include // 多线程中使用 QMutex mutex; QWaitCondition condition; QString curFilename; extern QList 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(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(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; }