157 lines
5.6 KiB
C++
157 lines
5.6 KiB
C++
#include "mainwindow.h"
|
|
#include <QHBoxLayout>
|
|
#include <QVBoxLayout>
|
|
#include <QGridLayout>
|
|
#include <QFileDialog>
|
|
#include <QScrollArea>
|
|
#include <QFrame>
|
|
#include <QGroupBox>
|
|
#include <QMessageBox>
|
|
|
|
MainWindow::MainWindow(QWidget *parent)
|
|
: QMainWindow(parent)
|
|
, m_updatingSeek(false)
|
|
{
|
|
setWindowTitle("Zero-Copy CUDA-GL Video Player");
|
|
resize(960, 600);
|
|
|
|
m_glWidget = new GLWidget(this);
|
|
m_videoDecoder = new VideoDecoder(this);
|
|
m_glWidget->setVideoDecoder(m_videoDecoder);
|
|
|
|
setupUI();
|
|
|
|
// Conectar las señales de posición y finalización del hilo descodificador
|
|
connect(m_videoDecoder, &VideoDecoder::positionChanged, this, &MainWindow::onPositionChanged);
|
|
connect(m_videoDecoder, &VideoDecoder::playbackFinished, this, &MainWindow::onPlaybackFinished);
|
|
}
|
|
|
|
MainWindow::~MainWindow() {
|
|
m_videoDecoder->stopThread();
|
|
}
|
|
|
|
void MainWindow::setupUI() {
|
|
// Aplicar hoja de estilos (QSS) para un look oscuro premium y retro-futurista
|
|
this->setStyleSheet(
|
|
"QMainWindow { background-color: #08080f; }"
|
|
"QWidget { color: #f0f0f5; font-family: 'Outfit', 'Segoe UI', sans-serif; font-size: 13px; }"
|
|
"QPushButton { background-color: #ff007f; color: white; border: none; padding: 8px 15px; border-radius: 6px; font-weight: bold; min-width: 60px; }"
|
|
"QPushButton:hover { background-color: #ff3399; }"
|
|
"QPushButton:pressed { background-color: #cc0066; }"
|
|
"QPushButton:disabled { background-color: #444; color: #888; }"
|
|
"QSlider::groove:horizontal { border: 1px solid #2d2d44; height: 6px; background: #1a1a2e; border-radius: 3px; }"
|
|
"QSlider::sub-page:horizontal { background: #ff007f; border-radius: 3px; }"
|
|
"QSlider::handle:horizontal { background: #ffffff; border: 1px solid #ff007f; width: 14px; height: 14px; margin: -4px 0; border-radius: 7px; }"
|
|
"QSlider::handle:horizontal:hover { background: #ff007f; }"
|
|
"QLabel { color: #a0a0c0; }"
|
|
);
|
|
|
|
QWidget *centralWidget = new QWidget(this);
|
|
setCentralWidget(centralWidget);
|
|
|
|
QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);
|
|
mainLayout->setContentsMargins(10, 10, 10, 10);
|
|
mainLayout->setSpacing(10);
|
|
|
|
mainLayout->addWidget(m_glWidget, 1);
|
|
|
|
// Controles Multimedia
|
|
QHBoxLayout *controlsLayout = new QHBoxLayout();
|
|
|
|
QPushButton *openBtn = new QPushButton("Abrir Video", this);
|
|
openBtn->setStyleSheet("background-color: #00bfff;");
|
|
connect(openBtn, &QPushButton::clicked, this, &MainWindow::openVideoFile);
|
|
controlsLayout->addWidget(openBtn);
|
|
|
|
m_playBtn = new QPushButton("▶", this);
|
|
connect(m_playBtn, &QPushButton::clicked, this, &MainWindow::togglePlayPause);
|
|
controlsLayout->addWidget(m_playBtn);
|
|
|
|
m_muteBtn = new QPushButton("🔊", this);
|
|
m_muteBtn->setStyleSheet("background-color: #4a4e69;");
|
|
connect(m_muteBtn, &QPushButton::clicked, this, &MainWindow::toggleMute);
|
|
controlsLayout->addWidget(m_muteBtn);
|
|
|
|
m_seekBar = new QSlider(Qt::Horizontal, this);
|
|
m_seekBar->setRange(0, 1000);
|
|
m_seekBar->setEnabled(false);
|
|
connect(m_seekBar, &QSlider::sliderMoved, this, &MainWindow::setVideoPosition);
|
|
controlsLayout->addWidget(m_seekBar, 1);
|
|
|
|
m_timeLabel = new QLabel("00:00 / 00:00", this);
|
|
m_timeLabel->setMinimumWidth(90);
|
|
m_timeLabel->setAlignment(Qt::AlignCenter);
|
|
controlsLayout->addWidget(m_timeLabel);
|
|
|
|
mainLayout->addLayout(controlsLayout);
|
|
}
|
|
|
|
void MainWindow::openVideoFile() {
|
|
QString fileName = QFileDialog::getOpenFileName(this, "Abrir archivo de video", "", "Videos (*.mp4 *.avi *.mkv *.webm *.mov)");
|
|
if (!fileName.isEmpty()) {
|
|
openVideoFileDirect(fileName);
|
|
}
|
|
}
|
|
|
|
void MainWindow::openVideoFileDirect(const QString &fileName) {
|
|
m_glWidget->clearVideo();
|
|
m_videoDecoder->stopThread();
|
|
|
|
if (m_videoDecoder->openFile(fileName)) {
|
|
m_seekBar->setEnabled(m_videoDecoder->getDuration() > 0.0);
|
|
m_playBtn->setText("⏸");
|
|
m_videoDecoder->start(); // Arranca el hilo de decodificación
|
|
m_videoDecoder->play(); // Inicia la reproducción
|
|
}
|
|
}
|
|
|
|
void MainWindow::togglePlayPause() {
|
|
if (m_videoDecoder->isPaused()) {
|
|
m_videoDecoder->play();
|
|
m_playBtn->setText("⏸");
|
|
} else {
|
|
m_videoDecoder->pause();
|
|
m_playBtn->setText("▶");
|
|
}
|
|
}
|
|
|
|
void MainWindow::toggleMute() {
|
|
static bool muted = false;
|
|
muted = !muted;
|
|
m_muteBtn->setText(muted ? "🔇" : "🔊");
|
|
}
|
|
|
|
void MainWindow::setVideoPosition(int position) {
|
|
if (m_videoDecoder->getDuration() > 0.0) {
|
|
m_updatingSeek = true;
|
|
double targetSecs = (static_cast<double>(position) / 1000.0) * m_videoDecoder->getDuration();
|
|
m_videoDecoder->seek(targetSecs);
|
|
m_updatingSeek = false;
|
|
}
|
|
}
|
|
|
|
void MainWindow::onPositionChanged(qint64 positionMs) {
|
|
double durationSecs = m_videoDecoder->getDuration();
|
|
if (durationSecs > 0.0 && !m_updatingSeek) {
|
|
m_updatingSeek = true;
|
|
double progress = static_cast<double>(positionMs) / (durationSecs * 1000.0);
|
|
m_seekBar->setValue(static_cast<int>(progress * 1000.0));
|
|
m_updatingSeek = false;
|
|
}
|
|
|
|
// Formatear tiempos
|
|
auto format = [](qint64 ms) -> QString {
|
|
qint64 totalSecs = ms / 1000;
|
|
int mins = totalSecs / 60;
|
|
int secs = totalSecs % 60;
|
|
return QString("%1:%2").arg(mins, 2, 10, QChar('0')).arg(secs, 2, 10, QChar('0'));
|
|
};
|
|
m_timeLabel->setText(format(positionMs) + " / " + format(static_cast<qint64>(durationSecs * 1000.0)));
|
|
}
|
|
|
|
void MainWindow::onPlaybackFinished() {
|
|
m_playBtn->setText("▶");
|
|
m_seekBar->setValue(0);
|
|
}
|
|
|
|
|