mirror of https://github.com/neutrinolabs/xrdp
560 lines
14 KiB
C++
560 lines
14 KiB
C++
#include "mainwindow.h"
|
|
#include "ui_mainwindow.h"
|
|
|
|
/*
|
|
* TODO
|
|
* o should we use tick marks in QSlider?
|
|
* o check for memory leaks
|
|
* o double click should make it full screen
|
|
* o when opening files, pause video
|
|
*/
|
|
|
|
MainWindow::MainWindow(QWidget *parent) :
|
|
QMainWindow(parent),
|
|
ui(new Ui::MainWindow)
|
|
{
|
|
gotMediaOnCmdline = false;
|
|
moveResizeTimer = NULL;
|
|
|
|
/* connect to remote client */
|
|
interface = new OurInterface();
|
|
if (interface->oneTimeInit())
|
|
{
|
|
oneTimeInitSuccess = false;
|
|
|
|
/* connection to remote client failed; error msg has */
|
|
/* already been displayed so it's ok to close app now */
|
|
QTimer::singleShot(1000, this, SLOT(close()));
|
|
}
|
|
else
|
|
{
|
|
oneTimeInitSuccess = true;
|
|
}
|
|
remoteClientInited = false;
|
|
ui->setupUi(this);
|
|
acceptSliderMove = false;
|
|
setupUI();
|
|
vcrFlag = 0;
|
|
|
|
connect(this, SIGNAL(onGeometryChanged(int,int,int,int)),
|
|
interface, SLOT(onGeometryChanged(int,int,int,int)));
|
|
|
|
connect(interface, SIGNAL(onMediaDurationInSeconds(int)),
|
|
this, SLOT(onMediaDurationInSeconds(int)));
|
|
|
|
/* if media file is specified on cmd line, use it */
|
|
QStringList args = QApplication::arguments();
|
|
if (args.count() > 1)
|
|
{
|
|
if (QFile::exists(args.at(1)))
|
|
{
|
|
interface->setFilename(args.at(1));
|
|
filename = args.at(1);
|
|
gotMediaOnCmdline = true;
|
|
on_actionOpen_Media_File_triggered();
|
|
}
|
|
else
|
|
{
|
|
QMessageBox::warning(this, "Invalid media file specified",
|
|
"\nThe media file\n\n" + args.at(1) +
|
|
"\n\ndoes not exist");
|
|
}
|
|
}
|
|
}
|
|
|
|
MainWindow::~MainWindow()
|
|
{
|
|
delete ui;
|
|
|
|
//if (moveResizeTimer)
|
|
// delete moveResizeTimer;
|
|
}
|
|
|
|
void MainWindow::closeEvent(QCloseEvent *event)
|
|
{
|
|
if (oneTimeInitSuccess)
|
|
{
|
|
interface->deInitRemoteClient();
|
|
}
|
|
else
|
|
{
|
|
QMessageBox::warning(this, "Closing application",
|
|
"This is not an xrdp session with xrdpvr");
|
|
}
|
|
event->accept();
|
|
}
|
|
|
|
void MainWindow::resizeEvent(QResizeEvent *)
|
|
{
|
|
//if (vcrFlag != VCR_PLAY)
|
|
{
|
|
QRect rect;
|
|
|
|
getVdoGeometry(&rect);
|
|
interface->sendGeometry(rect);
|
|
//return;
|
|
}
|
|
|
|
//interface->setVcrOp(VCR_PAUSE);
|
|
//vcrFlag = VCR_PAUSE;
|
|
|
|
//if (!moveResizeTimer)
|
|
//{
|
|
// moveResizeTimer = new QTimer;
|
|
// connect(moveResizeTimer, SIGNAL(timeout()),
|
|
// this, SLOT(onMoveCompleted()));
|
|
//}
|
|
//lblVideo->setStyleSheet("QLabel { background-color : black; color : blue; }");
|
|
//moveResizeTimer->start(1000);
|
|
}
|
|
|
|
void MainWindow::moveEvent(QMoveEvent *)
|
|
{
|
|
//if (vcrFlag != VCR_PLAY)
|
|
{
|
|
QRect rect;
|
|
|
|
getVdoGeometry(&rect);
|
|
interface->sendGeometry(rect);
|
|
//return;
|
|
}
|
|
|
|
//interface->setVcrOp(VCR_PAUSE);
|
|
//vcrFlag = VCR_PAUSE;
|
|
|
|
//if (!moveResizeTimer)
|
|
//{
|
|
// moveResizeTimer = new QTimer;
|
|
// connect(moveResizeTimer, SIGNAL(timeout()),
|
|
// this, SLOT(onMoveCompleted()));
|
|
//}
|
|
//lblVideo->setStyleSheet("QLabel { background-color : black; color : blue; }");
|
|
//moveResizeTimer->start(1000);
|
|
}
|
|
|
|
void MainWindow::onVolSliderValueChanged(int value)
|
|
{
|
|
int volume;
|
|
|
|
volume = (value * 0xffff) / 100;
|
|
if (interface != 0)
|
|
{
|
|
interface->setVolume(volume);
|
|
}
|
|
qDebug() << "vol = " << volume;
|
|
}
|
|
|
|
void MainWindow::setupUI()
|
|
{
|
|
this->setWindowTitle("vrplayer");
|
|
|
|
/* setup area to display video */
|
|
lblVideo = new QLabel();
|
|
lblVideo->setMinimumWidth(320);
|
|
lblVideo->setMinimumHeight(200);
|
|
QPalette palette = lblVideo->palette();
|
|
palette.setColor(lblVideo->backgroundRole(), QColor(0x00, 0x00, 0x01, 0xff));
|
|
palette.setColor(lblVideo->foregroundRole(), QColor(0x00, 0x00, 0x01, 0xff));
|
|
lblVideo->setAutoFillBackground(true);
|
|
lblVideo->setPalette(palette);
|
|
hboxLayoutTop = new QHBoxLayout;
|
|
hboxLayoutTop->addWidget(lblVideo);
|
|
|
|
/* setup label to display current pos in media */
|
|
lblCurrentPos = new QLabel("00:00:00");
|
|
lblCurrentPos->setMinimumHeight(20);
|
|
lblCurrentPos->setMaximumHeight(20);
|
|
|
|
/* setup slider to seek into media */
|
|
slider = new QSlider();
|
|
slider->setOrientation(Qt::Horizontal);
|
|
slider->setMinimumHeight(20);
|
|
slider->setMaximumHeight(20);
|
|
connect(slider, SIGNAL(actionTriggered(int)), this, SLOT(onSliderActionTriggered(int)));
|
|
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(onSliderValueChanged(int)));
|
|
|
|
/* setup label to display media duration */
|
|
lblDuration = new QLabel("00:00:00");
|
|
lblDuration->setMinimumHeight(20);
|
|
lblDuration->setMaximumHeight(20);
|
|
|
|
/* add above three widgets to mid layout */
|
|
hboxLayoutMiddle = new QHBoxLayout;
|
|
hboxLayoutMiddle->addWidget(lblCurrentPos);
|
|
hboxLayoutMiddle->addWidget(slider);
|
|
hboxLayoutMiddle->addWidget(lblDuration);
|
|
|
|
/* setup play button */
|
|
btnPlay = new QPushButton("Play");
|
|
btnPlay->setMinimumHeight(40);
|
|
btnPlay->setMaximumHeight(40);
|
|
btnPlay->setMinimumWidth(40);
|
|
btnPlay->setMaximumWidth(40);
|
|
btnPlay->setCheckable(true);
|
|
connect(btnPlay, SIGNAL(clicked(bool)),
|
|
this, SLOT(onBtnPlayClicked(bool)));
|
|
|
|
/* setup stop button */
|
|
btnStop = new QPushButton("Stop");
|
|
btnStop->setMinimumHeight(40);
|
|
btnStop->setMaximumHeight(40);
|
|
btnStop->setMinimumWidth(40);
|
|
btnStop->setMaximumWidth(40);
|
|
connect(btnStop, SIGNAL(clicked(bool)),
|
|
this, SLOT(onBtnStopClicked(bool)));
|
|
|
|
/* setup rewind button */
|
|
btnRewind = new QPushButton("R");
|
|
btnRewind->setMinimumHeight(40);
|
|
btnRewind->setMaximumHeight(40);
|
|
btnRewind->setMinimumWidth(40);
|
|
btnRewind->setMaximumWidth(40);
|
|
connect(btnRewind, SIGNAL(clicked(bool)),
|
|
this, SLOT(onBtnRewindClicked(bool)));
|
|
|
|
/* setup volume control slider */
|
|
volSlider = new QSlider();
|
|
volSlider->setOrientation(Qt::Horizontal);
|
|
volSlider->setMinimumWidth(100);
|
|
volSlider->setMaximumWidth(100);
|
|
volSlider->setMinimum(0);
|
|
volSlider->setMaximum(100);
|
|
volSlider->setValue(20);
|
|
volSlider->setTickPosition(QSlider::TicksAbove);
|
|
volSlider->setTickInterval(10);
|
|
|
|
connect(volSlider, SIGNAL(valueChanged(int)),
|
|
this, SLOT(onVolSliderValueChanged(int)));
|
|
|
|
/* add buttons to bottom panel */
|
|
hboxLayoutBottom = new QHBoxLayout;
|
|
hboxLayoutBottom->addWidget(btnPlay);
|
|
hboxLayoutBottom->addWidget(btnStop);
|
|
hboxLayoutBottom->addWidget(volSlider);
|
|
|
|
//hboxLayoutBottom->addWidget(btnRewind);
|
|
hboxLayoutBottom->addStretch();
|
|
|
|
/* add all three layouts to one vertical layout */
|
|
vboxLayout = new QVBoxLayout;
|
|
vboxLayout->addLayout(hboxLayoutTop);
|
|
vboxLayout->addLayout(hboxLayoutMiddle);
|
|
vboxLayout->addLayout(hboxLayoutBottom);
|
|
|
|
/* add all of them to central widget */
|
|
window = new QWidget;
|
|
window->setLayout(vboxLayout);
|
|
this->setCentralWidget(window);
|
|
}
|
|
|
|
void MainWindow::openMediaFile()
|
|
{
|
|
/* TODO take last stored value from QSettings */
|
|
|
|
if (filename.length() == 0)
|
|
{
|
|
|
|
/* no previous selection - open user's home folder TODO */
|
|
// TODO filename = QFileDialog::getOpenFileName(this, "Select Media File", "/");
|
|
//filename = QFileDialog::getOpenFileName(this, "Select Media File",
|
|
// QDir::currentPath());
|
|
|
|
filename = QFileDialog::getOpenFileName(this, "Select Media File",
|
|
QDir::currentPath(),
|
|
"Media *.mov *.mp4 *.mkv (*.mov *.mp4 *.mkv)");
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
/* show last selected file */
|
|
filename = QFileDialog::getOpenFileName(this, "Select Media File",
|
|
filename);
|
|
}
|
|
interface->setFilename(filename);
|
|
}
|
|
|
|
void MainWindow::getVdoGeometry(QRect *rect)
|
|
{
|
|
int x;
|
|
int y;
|
|
int width;
|
|
int height;
|
|
QPoint pt;
|
|
|
|
pt = lblVideo->mapToGlobal(QPoint(0, 0));
|
|
x = pt.x();
|
|
y = pt.y();
|
|
width = lblVideo->width();
|
|
height = lblVideo->height();
|
|
rect->setX(x);
|
|
rect->setY(y);
|
|
rect->setWidth(width);
|
|
rect->setHeight(height);
|
|
}
|
|
|
|
void MainWindow::clearDisplay()
|
|
{
|
|
/* TODO: this needs to be set after video actually stops
|
|
* a few frames come after this */
|
|
lblVideo->update();
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* actions and slots go here *
|
|
******************************************************************************/
|
|
|
|
void MainWindow::on_actionOpen_Media_File_triggered()
|
|
{
|
|
if (vcrFlag != 0)
|
|
{
|
|
onBtnStopClicked(true);
|
|
}
|
|
|
|
/* if media was specified on cmd line, use it just once */
|
|
if (gotMediaOnCmdline)
|
|
{
|
|
gotMediaOnCmdline = false;
|
|
}
|
|
else
|
|
{
|
|
openMediaFile();
|
|
}
|
|
|
|
if (filename.length() == 0)
|
|
{
|
|
/* cancel btn was clicked */
|
|
return;
|
|
}
|
|
|
|
if (remoteClientInited)
|
|
{
|
|
remoteClientInited = false;
|
|
interface->deInitRemoteClient();
|
|
if (interface->initRemoteClient() != 0)
|
|
{
|
|
QMessageBox::question(this, "vrplayer", "Unsupported codec",
|
|
QMessageBox::Ok);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (interface->initRemoteClient() != 0)
|
|
{
|
|
QMessageBox::question(this, "vrplayer", "Unsupported codec",
|
|
QMessageBox::Ok);
|
|
return;
|
|
}
|
|
}
|
|
|
|
demuxMedia = interface->getDemuxMediaInstance();
|
|
if (demuxMedia)
|
|
{
|
|
connect(demuxMedia, SIGNAL(onElapsedtime(int)),
|
|
this, SLOT(onElapsedTime(int)));
|
|
}
|
|
|
|
remoteClientInited = true;
|
|
interface->playMedia();
|
|
|
|
//if (vcrFlag != 0)
|
|
{
|
|
interface->setVcrOp(VCR_PLAY);
|
|
btnPlay->setText("Pause");
|
|
vcrFlag = VCR_PLAY;
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_actionExit_triggered()
|
|
{
|
|
clearDisplay();
|
|
this->close();
|
|
}
|
|
|
|
void MainWindow::onBtnPlayClicked(bool)
|
|
{
|
|
if (vcrFlag == 0)
|
|
{
|
|
/* first time play button3 has been clicked */
|
|
on_actionOpen_Media_File_triggered();
|
|
btnPlay->setText("Pause");
|
|
vcrFlag = VCR_PLAY;
|
|
}
|
|
else if (vcrFlag == VCR_PLAY)
|
|
{
|
|
/* btn clicked while in play mode - enter pause mode */
|
|
btnPlay->setText("Play");
|
|
interface->setVcrOp(VCR_PAUSE);
|
|
vcrFlag = VCR_PAUSE;
|
|
}
|
|
else if (vcrFlag == VCR_PAUSE)
|
|
{
|
|
/* btn clicked while in pause mode - enter play mode */
|
|
btnPlay->setText("Pause");
|
|
interface->setVcrOp(VCR_PLAY);
|
|
vcrFlag = VCR_PLAY;
|
|
}
|
|
else if (vcrFlag == VCR_STOP)
|
|
{
|
|
/* btn clicked while stopped - enter play mode */
|
|
btnPlay->setText("Play");
|
|
interface->setVcrOp(VCR_PLAY);
|
|
vcrFlag = VCR_PLAY;
|
|
}
|
|
}
|
|
|
|
void MainWindow::onBtnRewindClicked(bool)
|
|
{
|
|
//if (playVideo)
|
|
// playVideo->onMediaSeek(0);
|
|
}
|
|
|
|
void MainWindow::onBtnStopClicked(bool)
|
|
{
|
|
vcrFlag = VCR_STOP;
|
|
btnPlay->setText("Play");
|
|
interface->setVcrOp(VCR_STOP);
|
|
|
|
/* reset slider */
|
|
slider->setSliderPosition(0);
|
|
lblCurrentPos->setText("00:00:00");
|
|
|
|
/* clear screen by filling it with black */
|
|
usleep(500 * 1000);
|
|
clearDisplay();
|
|
|
|
btnPlay->setChecked(false);
|
|
}
|
|
|
|
void MainWindow::onMediaDurationInSeconds(int duration)
|
|
{
|
|
int hours = 0;
|
|
int minutes = 0;
|
|
int secs = 0;
|
|
char buf[20];
|
|
|
|
/* setup progress bar */
|
|
slider->setMinimum(0);
|
|
slider->setMaximum(duration * 100); /* in hundredth of a sec */
|
|
slider->setValue(0);
|
|
slider->setSliderPosition(0);
|
|
lblCurrentPos->setText("00:00:00");
|
|
//qDebug() << "media_duration=" << duration << " in hundredth of a sec:" << duration * 100;
|
|
|
|
/* convert from seconds to hours:minutes:seconds */
|
|
hours = duration / 3600;
|
|
if (hours)
|
|
duration -= (hours * 3600);
|
|
|
|
minutes = duration / 60;
|
|
if (minutes)
|
|
duration -= minutes * 60;
|
|
|
|
secs = duration;
|
|
|
|
sprintf(buf, "%.2d:%.2d:%.2d", hours, minutes, secs);
|
|
lblDuration->setText(QString(buf));
|
|
}
|
|
|
|
/**
|
|
* time elapsed in 1/100th sec units since play started
|
|
******************************************************************************/
|
|
void MainWindow::onElapsedTime(int val)
|
|
{
|
|
int hours = 0;
|
|
int minutes = 0;
|
|
int secs = 0;
|
|
int duration = 0;
|
|
char buf[20];
|
|
|
|
if (vcrFlag == VCR_STOP)
|
|
return;
|
|
|
|
/* if slider bar is down, do not update */
|
|
if (slider->isSliderDown())
|
|
return;
|
|
|
|
/* update progress bar */
|
|
if (val >= slider->maximum())
|
|
val = 0;
|
|
|
|
slider->setSliderPosition(val);
|
|
|
|
/* convert from seconds to hours:minutes:seconds */
|
|
duration = val / 100;
|
|
hours = duration / 3600;
|
|
if (hours)
|
|
duration -= (hours * 3600);
|
|
|
|
minutes = duration / 60;
|
|
if (minutes)
|
|
duration -= minutes * 60;
|
|
|
|
secs = duration;
|
|
|
|
/* update current position in progress bar */
|
|
sprintf(buf, "%.2d:%.2d:%.2d", hours, minutes, secs);
|
|
lblCurrentPos->setText(QString(buf));
|
|
}
|
|
|
|
void MainWindow::onSliderValueChanged(int value)
|
|
{
|
|
if (acceptSliderMove)
|
|
{
|
|
acceptSliderMove = false;
|
|
if (demuxMedia != NULL)
|
|
{
|
|
demuxMedia->onMediaSeek(value / 100);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::onSliderActionTriggered(int action)
|
|
{
|
|
switch (action)
|
|
{
|
|
case QAbstractSlider::SliderPageStepAdd:
|
|
acceptSliderMove = true;
|
|
break;
|
|
|
|
case QAbstractSlider::SliderPageStepSub:
|
|
acceptSliderMove = true;
|
|
break;
|
|
|
|
case QAbstractSlider::SliderMove:
|
|
if (slider->isSliderDown())
|
|
acceptSliderMove = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// not called
|
|
void MainWindow::onMoveCompleted()
|
|
{
|
|
QRect rect;
|
|
|
|
getVdoGeometry(&rect);
|
|
interface->sendGeometry(rect);
|
|
|
|
interface->setVcrOp(VCR_PLAY);
|
|
vcrFlag = VCR_PLAY;
|
|
//moveResizeTimer->stop();
|
|
}
|
|
|
|
void MainWindow::on_actionAbout_triggered()
|
|
{
|
|
#if 0
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setText("VRPlayer version 1.2");
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
msgBox.setDefaultButton(QMessageBox::Ok);
|
|
msgBox.exec();
|
|
#else
|
|
DlgAbout *dlgabt = new DlgAbout(this);
|
|
dlgabt->exec();
|
|
|
|
#endif
|
|
}
|