citra_qt/dumping: Add dumping dialog
This is the main dialog of video dumping. This dialog allows the user to set output format, output path, video/audio encoder and video/audio bitrate. When a format is selected, the list of video and audio encoders are updated. Only encoders of codecs that can be contained in the format is shown.
This commit is contained in:
210
src/citra_qt/dumping/dumping_dialog.cpp
Normal file
210
src/citra_qt/dumping/dumping_dialog.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
// Copyright 2020 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include "citra_qt/dumping/dumping_dialog.h"
|
||||
#include "citra_qt/dumping/options_dialog.h"
|
||||
#include "citra_qt/uisettings.h"
|
||||
#include "core/settings.h"
|
||||
#include "ui_dumping_dialog.h"
|
||||
|
||||
DumpingDialog::DumpingDialog(QWidget* parent)
|
||||
: QDialog(parent), ui(std::make_unique<Ui::DumpingDialog>()) {
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
connect(ui->pathExplore, &QToolButton::clicked, this, &DumpingDialog::OnToolButtonClicked);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, [this] {
|
||||
ApplyConfiguration();
|
||||
accept();
|
||||
});
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &DumpingDialog::reject);
|
||||
connect(ui->formatOptionsButton, &QPushButton::clicked, [this] {
|
||||
OpenOptionsDialog(formats.at(ui->formatComboBox->currentData().toUInt()).options,
|
||||
format_options);
|
||||
});
|
||||
connect(ui->videoEncoderOptionsButton, &QPushButton::clicked, [this] {
|
||||
OpenOptionsDialog(
|
||||
video_encoders.at(ui->videoEncoderComboBox->currentData().toUInt()).options,
|
||||
video_encoder_options);
|
||||
});
|
||||
connect(ui->audioEncoderOptionsButton, &QPushButton::clicked, [this] {
|
||||
OpenOptionsDialog(
|
||||
audio_encoders.at(ui->audioEncoderComboBox->currentData().toUInt()).options,
|
||||
audio_encoder_options);
|
||||
});
|
||||
|
||||
SetConfiguration();
|
||||
|
||||
connect(ui->formatComboBox, qOverload<int>(&QComboBox::currentIndexChanged), [this] {
|
||||
ui->pathLineEdit->setText(QString{});
|
||||
format_options.clear();
|
||||
PopulateEncoders();
|
||||
});
|
||||
|
||||
connect(ui->videoEncoderComboBox, qOverload<int>(&QComboBox::currentIndexChanged),
|
||||
[this] { video_encoder_options.clear(); });
|
||||
connect(ui->audioEncoderComboBox, qOverload<int>(&QComboBox::currentIndexChanged),
|
||||
[this] { audio_encoder_options.clear(); });
|
||||
}
|
||||
|
||||
DumpingDialog::~DumpingDialog() = default;
|
||||
|
||||
QString DumpingDialog::GetFilePath() const {
|
||||
return ui->pathLineEdit->text();
|
||||
}
|
||||
|
||||
void DumpingDialog::Populate() {
|
||||
formats = VideoDumper::ListFormats();
|
||||
video_encoders = VideoDumper::ListEncoders(AVMEDIA_TYPE_VIDEO);
|
||||
audio_encoders = VideoDumper::ListEncoders(AVMEDIA_TYPE_AUDIO);
|
||||
|
||||
// Check that these are not empty
|
||||
QString missing;
|
||||
if (formats.empty()) {
|
||||
missing = tr("output formats");
|
||||
}
|
||||
if (video_encoders.empty()) {
|
||||
missing = tr("video encoders");
|
||||
}
|
||||
if (audio_encoders.empty()) {
|
||||
missing = tr("audio encoders");
|
||||
}
|
||||
|
||||
if (!missing.isEmpty()) {
|
||||
QMessageBox::critical(this, tr("Citra"),
|
||||
tr("Could not find any available %1.\nPlease check your FFmpeg "
|
||||
"installation used for compilation.")
|
||||
.arg(missing));
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
|
||||
// Populate formats
|
||||
for (std::size_t i = 0; i < formats.size(); ++i) {
|
||||
const auto& format = formats[i];
|
||||
|
||||
// Check format: only formats that have video encoders and audio encoders are displayed
|
||||
bool has_video = false;
|
||||
for (const auto& video_encoder : video_encoders) {
|
||||
if (format.supported_video_codecs.count(video_encoder.codec)) {
|
||||
has_video = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!has_video)
|
||||
continue;
|
||||
|
||||
bool has_audio = false;
|
||||
for (const auto& audio_encoder : audio_encoders) {
|
||||
if (format.supported_audio_codecs.count(audio_encoder.codec)) {
|
||||
has_audio = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!has_audio)
|
||||
continue;
|
||||
|
||||
ui->formatComboBox->addItem(tr("%1 (%2)").arg(QString::fromStdString(format.long_name),
|
||||
QString::fromStdString(format.name)),
|
||||
static_cast<unsigned long long>(i));
|
||||
if (format.name == Settings::values.output_format) {
|
||||
ui->formatComboBox->setCurrentIndex(ui->formatComboBox->count() - 1);
|
||||
}
|
||||
}
|
||||
PopulateEncoders();
|
||||
}
|
||||
|
||||
void DumpingDialog::PopulateEncoders() {
|
||||
const auto& format = formats.at(ui->formatComboBox->currentData().toUInt());
|
||||
|
||||
ui->videoEncoderComboBox->clear();
|
||||
for (std::size_t i = 0; i < video_encoders.size(); ++i) {
|
||||
const auto& video_encoder = video_encoders[i];
|
||||
if (!format.supported_video_codecs.count(video_encoder.codec)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ui->videoEncoderComboBox->addItem(
|
||||
tr("%1 (%2)").arg(QString::fromStdString(video_encoder.long_name),
|
||||
QString::fromStdString(video_encoder.name)),
|
||||
static_cast<unsigned long long>(i));
|
||||
if (video_encoder.name == Settings::values.video_encoder) {
|
||||
ui->videoEncoderComboBox->setCurrentIndex(ui->videoEncoderComboBox->count() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
ui->audioEncoderComboBox->clear();
|
||||
for (std::size_t i = 0; i < audio_encoders.size(); ++i) {
|
||||
const auto& audio_encoder = audio_encoders[i];
|
||||
if (!format.supported_audio_codecs.count(audio_encoder.codec)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ui->audioEncoderComboBox->addItem(
|
||||
tr("%1 (%2)").arg(QString::fromStdString(audio_encoder.long_name),
|
||||
QString::fromStdString(audio_encoder.name)),
|
||||
static_cast<unsigned long long>(i));
|
||||
if (audio_encoder.name == Settings::values.audio_encoder) {
|
||||
ui->audioEncoderComboBox->setCurrentIndex(ui->audioEncoderComboBox->count() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DumpingDialog::OnToolButtonClicked() {
|
||||
const auto& format = formats.at(ui->formatComboBox->currentData().toUInt());
|
||||
|
||||
QString extensions;
|
||||
for (const auto& ext : format.extensions) {
|
||||
if (!extensions.isEmpty()) {
|
||||
extensions.append(QLatin1Char{' '});
|
||||
}
|
||||
extensions.append(QStringLiteral("*.%1").arg(QString::fromStdString(ext)));
|
||||
}
|
||||
|
||||
const auto path = QFileDialog::getSaveFileName(
|
||||
this, tr("Select Video Output Path"), last_path,
|
||||
tr("%1 (%2)").arg(QString::fromStdString(format.long_name), extensions));
|
||||
if (!path.isEmpty()) {
|
||||
last_path = QFileInfo(ui->pathLineEdit->text()).path();
|
||||
ui->pathLineEdit->setText(path);
|
||||
}
|
||||
}
|
||||
|
||||
void DumpingDialog::OpenOptionsDialog(const std::vector<VideoDumper::OptionInfo>& options,
|
||||
std::string& current_value) {
|
||||
OptionsDialog dialog(this, options, current_value);
|
||||
if (dialog.exec() != QDialog::DialogCode::Accepted) {
|
||||
return;
|
||||
}
|
||||
|
||||
current_value = dialog.GetCurrentValue();
|
||||
}
|
||||
|
||||
void DumpingDialog::SetConfiguration() {
|
||||
Populate();
|
||||
|
||||
format_options = Settings::values.format_options;
|
||||
video_encoder_options = Settings::values.video_encoder_options;
|
||||
audio_encoder_options = Settings::values.audio_encoder_options;
|
||||
last_path = UISettings::values.video_dumping_path;
|
||||
ui->videoBitrateSpinBox->setValue(static_cast<int>(Settings::values.video_bitrate));
|
||||
ui->audioBitrateSpinBox->setValue(static_cast<int>(Settings::values.audio_bitrate));
|
||||
}
|
||||
|
||||
void DumpingDialog::ApplyConfiguration() {
|
||||
Settings::values.output_format = formats.at(ui->formatComboBox->currentData().toUInt()).name;
|
||||
Settings::values.format_options = format_options;
|
||||
Settings::values.video_encoder =
|
||||
video_encoders.at(ui->videoEncoderComboBox->currentData().toUInt()).name;
|
||||
Settings::values.video_encoder_options = video_encoder_options;
|
||||
Settings::values.video_bitrate = ui->videoBitrateSpinBox->value();
|
||||
Settings::values.audio_encoder =
|
||||
audio_encoders.at(ui->audioEncoderComboBox->currentData().toUInt()).name;
|
||||
Settings::values.audio_encoder_options = audio_encoder_options;
|
||||
Settings::values.audio_bitrate = ui->audioBitrateSpinBox->value();
|
||||
UISettings::values.video_dumping_path = last_path;
|
||||
Settings::Apply();
|
||||
}
|
Reference in New Issue
Block a user