File indexing completed on 2024-04-28 15:16:13
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"