File indexing completed on 2024-04-14 03:48:09

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2014 Sanjiban Bairagya <sanjiban22393@gmail.com>
0004 //
0005 
0006 #include "TourCaptureDialog.h"
0007 #include "ui_TourCaptureDialog.h"
0008 
0009 #include <QFileDialog>
0010 #include <QMessageBox>
0011 #include <QTimer>
0012 
0013 #include "MarbleWidget.h"
0014 #include "MovieCapture.h"
0015 #include "TourPlayback.h"
0016 
0017 namespace Marble {
0018 
0019 TourCaptureDialog::TourCaptureDialog(MarbleWidget *widget, QWidget *parent) :
0020     QDialog(parent),
0021     ui(new Ui::TourCaptureDialog),
0022     m_recorder(new MovieCapture(widget, parent)),
0023     m_playback(nullptr),
0024     m_writingPossible( true ),
0025     m_current_position( 0.0 )
0026 {
0027     ui->setupUi(this);
0028     m_recorder->setSnapshotMethod(MovieCapture::DataDriven);
0029     ui->progressBar->setValue(0);
0030 
0031     connect(ui->fpsSlider, SIGNAL(valueChanged(int)),
0032             ui->fpsSpin, SLOT(setValue(int)));
0033 
0034     connect(ui->fpsSpin, SIGNAL(valueChanged(int)),
0035             ui->fpsSlider, SLOT(setValue(int)));
0036 
0037     connect(ui->fpsSlider, SIGNAL(valueChanged(int)),
0038             m_recorder, SLOT(setFps(int)));
0039 
0040     connect(ui->closeButton, SIGNAL(clicked()),
0041             this, SLOT(close()));
0042 
0043     connect(ui->startButton, SIGNAL(clicked()),
0044             this, SLOT(startRecording()));
0045 
0046     connect(ui->openButton, SIGNAL(clicked()),
0047             this, SLOT(loadDestinationFile()));
0048 
0049     connect(m_recorder, SIGNAL(rateCalculated(double)),
0050             this, SLOT(setRate(double))) ;
0051 
0052     connect(m_recorder, SIGNAL(errorOccured()),
0053             this, SLOT(handleError()) );
0054 }
0055 
0056 TourCaptureDialog::~TourCaptureDialog()
0057 {
0058     delete ui;
0059 }
0060 
0061 void TourCaptureDialog::loadDestinationFile()
0062 {
0063     const QVector<MovieFormat> formats = m_recorder->availableFormats();
0064     if( formats.isEmpty() ) {
0065         QMessageBox::warning( this, tr( "Codecs are unavailable" ), tr( "Supported codecs are not found. (ffmpeg/avconv needs to be installed and in PATH.)" ) );
0066         return;
0067     }
0068     QString filter = formats.first().name() + QLatin1String(" (*.") + formats.first().extension() + QLatin1Char(')');
0069     for( int i = 1; i < formats.size(); i++ )
0070     {
0071         filter += QLatin1String(";;") + formats.at(i).name() + QLatin1String(" (*.") + formats.at(i).extension() + QLatin1Char(')');
0072     }
0073     const QString defaultFileName =
0074             ui->destinationEdit->text().isEmpty() ? m_defaultFileName : ui->destinationEdit->text();
0075 
0076     const QString destination =
0077             QFileDialog::getSaveFileName(this, tr("Save video file"), defaultFileName,
0078                                          filter );
0079 
0080     if (destination.isEmpty()) {
0081         return;
0082     }
0083 
0084     bool supported = false;
0085     for(const MovieFormat &format: formats) {
0086         if (destination.endsWith(QLatin1Char('.') + format.extension())) {
0087             supported = true;
0088             break;
0089         }
0090     }
0091 
0092     if (!supported) {
0093         QString formatsExtensions = QLatin1Char('.') + formats.at(0).extension();
0094         for( int i = 1; i < formats.size(); ++i )
0095         {
0096             formatsExtensions += QLatin1String(", .") + formats.at(i).extension();
0097         }
0098         QMessageBox::warning(this, tr("Filename is not valid"),
0099                              tr("This file format is not supported. "
0100                                 "Please, use %1 instead").arg( formatsExtensions ) );
0101         return;
0102     }
0103 
0104     ui->destinationEdit->setText(destination);
0105     m_recorder->setFilename(destination);
0106 }
0107 
0108 void TourCaptureDialog::startRecording()
0109 {
0110     if( ui->startButton->text() == tr("Start") ){
0111         ui->startButton->setText(tr("Cancel"));
0112         ui->closeButton->setDisabled(true);
0113         const QString path = ui->destinationEdit->text();
0114 
0115         if( path.isEmpty() ){
0116             QMessageBox::warning(this, tr("Missing filename"),
0117                            tr("Destination video file is not set. "
0118                               "I don't know where to save recorded "
0119                               "video. Please, specify one."));
0120             return;
0121         }
0122 
0123         m_recorder->setSnapshotMethod( MovieCapture::DataDriven );
0124         m_recorder->setFps(ui->fpsSlider->value());
0125         m_recorder->startRecording();
0126         m_current_position = 0.0;
0127         recordNextFrame();
0128     }
0129     else{
0130         ui->startButton->setText(tr("Start"));
0131         m_recorder->cancelRecording();
0132         ui->progressBar->setValue(0);
0133         ui->closeButton->setEnabled(true);
0134     }
0135 }
0136 
0137 void TourCaptureDialog::updateProgress(double position)
0138 {
0139     ui->progressBar->setValue(position);
0140 }
0141 
0142 void TourCaptureDialog::recordNextFrame()
0143 {
0144     double const shift = 1.0 / ( ui->fpsSlider->value() );
0145     double const duration = m_playback->duration();
0146 
0147     if (!m_writingPossible) {
0148         ui->rate->setText(QString("<font color=\"red\">%1</font>").arg(tr("Video writing failed.")));
0149         return;
0150     }
0151 
0152     if (ui->startButton->text() == QLatin1String("Start")) {
0153         return;
0154     }
0155 
0156     if (m_current_position <= duration) {
0157         m_playback->seek( m_current_position );
0158         m_recorder->recordFrame();
0159         updateProgress( m_current_position * 100 );
0160         m_current_position += shift;
0161         QTimer::singleShot(1, this, SLOT(recordNextFrame()));
0162     } else {
0163         m_recorder->stopRecording();
0164         ui->progressBar->setValue(duration*100);
0165         ui->startButton->setText(tr("Start"));
0166         ui->rate->setText(QString("<font color=\"green\">%1</font>").arg(tr("Video export completed.")));
0167         ui->closeButton->setEnabled(true);
0168     }
0169 }
0170 
0171 void TourCaptureDialog::setRate(double rate)
0172 {
0173     ui->rate->setText(QString("%1 KBytes/sec").arg(rate));
0174 }
0175 
0176 void TourCaptureDialog::stopRecording()
0177 {
0178     m_recorder->stopRecording();
0179 }
0180 
0181 void TourCaptureDialog::setTourPlayback( TourPlayback* playback )
0182 {
0183     m_playback = playback;
0184     ui->progressBar->setMaximum(playback->duration() * 100);
0185 }
0186 
0187 void TourCaptureDialog::setDefaultFilename(const QString &filename)
0188 {
0189     m_defaultFileName = filename;
0190 }
0191 
0192 void TourCaptureDialog::handleError()
0193 {
0194     m_writingPossible = false;
0195 }
0196 
0197 } // namespace Marble
0198 
0199 #include "moc_TourCaptureDialog.cpp"