///////////////////////////////////////////////////////////////////////////////
// Simple x264 Launcher
-// Copyright (C) 2004-2015 LoRd_MuldeR <MuldeR2@GMX.de>
+// Copyright (C) 2004-2020 LoRd_MuldeR <MuldeR2@GMX.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
#include "model_recently.h"
#include "encoder_factory.h"
#include "mediainfo.h"
+#include "string_validator.h"
#include "win_help.h"
#include "win_editor.h"
//MUtils
#include <MUtils/Global.h>
+#include <MUtils/OSSupport.h>
#include <MUtils/Exception.h>
//Qt
Q_DECLARE_METATYPE(const void*)
///////////////////////////////////////////////////////////////////////////////
-// Validator
+// Disable Monitoring RAII
///////////////////////////////////////////////////////////////////////////////
-class StringValidator : public QValidator
+class DisableHelperRAII
{
public:
- StringValidator(QLabel *notifier, QLabel *icon)
- :
- m_notifier(notifier), m_icon(icon)
+ DisableHelperRAII(bool *const flag) : m_flag(flag)
{
- m_notifier->hide();
- m_icon->hide();
- }
-
- virtual State validate(QString &input, int &pos) const = 0;
-
- virtual void fixup(QString &input) const
- {
- input = input.simplified();
- }
-
-protected:
- QLabel *const m_notifier, *const m_icon;
-
- bool checkParam(const QString &input, const QString ¶m, const bool doubleMinus) const
- {
- static const char c[20] = {' ', '*', '?', '<', '>', '/', '\\', '"', '\'', '!', '+', '#', '&', '%', '=', ',', ';', '.', 'ยด', '`'};
- const QString prefix = doubleMinus ? QLatin1String("--") : QLatin1String("-");
-
- bool flag = false;
- if(param.length() > 1)
- {
- flag = flag || input.endsWith(QString("%1%2").arg(prefix, param), Qt::CaseInsensitive);
- for(size_t i = 0; i < sizeof(c); i++)
- {
- flag = flag || input.contains(QString("%1%2%3").arg(prefix, param, QChar::fromLatin1(c[i])), Qt::CaseInsensitive);
- }
- }
- else
- {
- flag = flag || input.startsWith(QString("-%1").arg(param));
- for(size_t i = 0; i < sizeof(c); i++)
- {
- flag = flag || input.contains(QString("%1-%2").arg(QChar::fromLatin1(c[i]), param), Qt::CaseSensitive);
- }
- }
- if((flag) && (m_notifier))
- {
- m_notifier->setText(tr("Invalid parameter: %1").arg((param.length() > 1) ? QString("%1%2").arg(prefix, param) : QString("-%1").arg(param)));
- }
- return flag;
+ *m_flag = false;
}
- bool checkPrefix(const QString &input) const
+ ~DisableHelperRAII(void)
{
- static const char *const c[3] = { "--", "-", NULL };
- for(size_t i = 0; c[i]; i++)
- {
- const QString prefix = QString::fromLatin1(c[i]);
- if(input.startsWith(QString("%1 ").arg(prefix)) || input.contains(QString(" %1 ").arg(prefix)) || input.endsWith(prefix))
- {
- qDebug("A");
- if(m_notifier)
- {
- m_notifier->setText(tr("Invalid parameter: %1").arg(prefix));
- }
- return true;
- }
- }
- return false;
- }
-
- const bool &setStatus(const bool &flag, const QString &toolName) const
- {
- if(flag)
- {
- if(m_notifier)
- {
- if(m_notifier->isHidden()) m_notifier->show();
- if(m_icon) { if(m_icon->isHidden()) m_icon->show(); }
- if(QWidget *w = m_notifier->topLevelWidget()->focusWidget())
- {
- QToolTip::showText(static_cast<QWidget*>(w->parent())->mapToGlobal(w->pos()), tr("<b>Warning:</b> You entered a parameter that is forbidden. Please note that the GUI will automatically set <i>this</i> parameter for you (if required)."), m_notifier, QRect());
- }
- }
- }
- else
- {
- if(m_notifier)
- {
- if(m_notifier->isVisible()) m_notifier->hide();
- if(m_icon) { if(m_icon->isVisible()) m_icon->hide(); }
- QToolTip::hideText();
- }
- }
- return flag;
+ *m_flag = true;
}
-};
-
-class StringValidatorX264 : public StringValidator
-{
-public:
- StringValidatorX264(QLabel *notifier, QLabel *icon) : StringValidator(notifier, icon) {}
-
- virtual State validate(QString &input, int &pos) const
- {
- static const char* p[] = {"B", "o", "h", "p", "q", /*"fps", "frames",*/ "preset", "tune", "profile",
- "stdin", "crf", "bitrate", "qp", "pass", "stats", "output", "help","quiet", NULL};
-
- bool invalid = checkPrefix(input);
- for(size_t i = 0; p[i] && (!invalid); i++)
- {
- invalid = invalid || checkParam(input, QString::fromLatin1(p[i]), true);
- }
-
- return setStatus(invalid, "encoder") ? QValidator::Intermediate : QValidator::Acceptable;
- }
-};
-
-class StringValidatorAvs2YUV : public StringValidator
-{
-public:
- StringValidatorAvs2YUV(QLabel *notifier, QLabel *icon) : StringValidator(notifier, icon) {}
-
- virtual State validate(QString &input, int &pos) const
- {
- static const char* p[] = {"o", "frames", "seek", "raw", "hfyu", "slave", NULL};
-
- bool invalid = checkPrefix(input);
-
- for(size_t i = 0; p[i] && (!invalid); i++)
- {
- invalid = invalid || checkParam(input, QString::fromLatin1(p[i]), false);
- }
-
- return setStatus(invalid, "Avs2YUV") ? QValidator::Intermediate : QValidator::Acceptable;
- }
+private:
+ bool *const m_flag;
};
///////////////////////////////////////////////////////////////////////////////
m_preferences(preferences),
m_defaults(new OptionsModel(sysinfo)),
ui(new Ui::AddJobDialog()),
- m_monitorConfigChanges(true)
+ m_monitorConfigChanges(false)
{
//Init the dialog, from the .ui file
ui->setupUi(this);
setMaximumHeight(height());
//Init encoder combobox
- ui->cbxEncoderType->addItem(tr("x264 (AVC)"), OptionsModel::EncType_X264);
+ ui->cbxEncoderType->addItem(tr("x264 (AVC)"), OptionsModel::EncType_X264);
ui->cbxEncoderType->addItem(tr("x265 (HEVC)"), OptionsModel::EncType_X265);
-
- //Init arch combobox
- ui->cbxEncoderArch->addItem(tr("32-Bit"), OptionsModel::EncArch_x86_32);
- ui->cbxEncoderArch->addItem(tr("64-Bit"), OptionsModel::EncArch_x86_64);
-
- //Init rc-mode combobox
- ui->cbxRateControlMode->addItem(tr("CRF"), OptionsModel::RCMode_CRF);
- ui->cbxRateControlMode->addItem(tr("CQ"), OptionsModel::RCMode_CQ);
- ui->cbxRateControlMode->addItem(tr("2-Pass"), OptionsModel::RCMode_2Pass);
- ui->cbxRateControlMode->addItem(tr("ABR"), OptionsModel::RCMode_ABR);
+ ui->cbxEncoderType->addItem(tr("NVEncC"), OptionsModel::EncType_NVEnc);
//Init combobox items
- ui->cbxTuning ->addItem(QString::fromLatin1(OptionsModel::TUNING_UNSPECIFIED));
+ ui->cbxTuning ->addItem(QString::fromLatin1(OptionsModel::SETTING_UNSPECIFIED));
ui->cbxProfile->addItem(QString::fromLatin1(OptionsModel::PROFILE_UNRESTRICTED));
//Hide optional controls
//Setup validator
ui->editCustomX264Params->installEventFilter(this);
- ui->editCustomX264Params->setValidator(new StringValidatorX264(ui->labelNotificationX264, ui->iconNotificationX264));
+ ui->editCustomX264Params->setValidator(new StringValidatorEncoder(ui->labelNotificationX264, ui->iconNotificationX264));
ui->editCustomX264Params->clear();
ui->editCustomAvs2YUVParams->installEventFilter(this);
- ui->editCustomAvs2YUVParams->setValidator(new StringValidatorAvs2YUV(ui->labelNotificationAvs2YUV, ui->iconNotificationAvs2YUV));
+ ui->editCustomAvs2YUVParams->setValidator(new StringValidatorSource(ui->labelNotificationAvs2YUV, ui->iconNotificationAvs2YUV));
ui->editCustomAvs2YUVParams->clear();
//Install event filter
//Setup template selector
loadTemplateList();
connect(ui->cbxTemplate, SIGNAL(currentIndexChanged(int)), this, SLOT(templateSelected()));
+
+ //Force initial UI update
+ encoderIndexChanged(ui->cbxEncoderType->currentIndex());
+ m_monitorConfigChanges = true;
}
AddJobDialog::~AddJobDialog(void)
const OptionsModel::EncType encType = static_cast<OptionsModel::EncType>(ui->cbxEncoderType->itemData(ui->cbxEncoderType->currentIndex()).toInt());
const AbstractEncoderInfo &encoderInfo = EncoderFactory::getEncoderInfo(encType);
+ //Update encoder architectures
+ const QList<AbstractEncoderInfo::ArchId> archs = encoderInfo.getArchitectures();
+ ui->cbxEncoderArch->clear();
+ for (quint32 archIdx = 0; archIdx < quint32(archs.count()); ++archIdx)
+ {
+ ui->cbxEncoderArch->addItem(archs[archIdx].first, archIdx);
+ }
+
//Update encoder variants
- const QFlags<OptionsModel::EncVariant> variants = encoderInfo.getVariants();
+ const QStringList variants = encoderInfo.getVariants();
ui->cbxEncoderVariant->clear();
- for(OptionsModel::EncVariant varnt = OptionsModel::EncVariant_MIN; varnt <= OptionsModel::EncVariant_MAX; SHFL(varnt))
+ for(quint32 varntIdx = 0; varntIdx < quint32(variants.count()); ++varntIdx)
{
- if(variants.testFlag(varnt))
- {
- QString varntText;
- switch(varnt)
- {
- case OptionsModel::EncVariant_8Bit: varntText = tr("8-Bit"); break;
- case OptionsModel::EncVariant_10Bit: varntText = tr("10-Bit"); break;
- case OptionsModel::EncVariant_12Bit: varntText = tr("12-Bit"); break;
- default: MUTILS_THROW("Bad encoder variant!");
- }
- ui->cbxEncoderVariant->addItem(varntText, QVariant(varnt));
- }
+ ui->cbxEncoderVariant->addItem(variants[varntIdx], varntIdx);
+ }
+
+ //Update encoder RC modes
+ const QList<AbstractEncoderInfo::RCMode> rcModes = encoderInfo.getRCModes();
+ ui->cbxRateControlMode->clear();
+ for (quint32 rcIndex = 0; rcIndex < quint32(rcModes.count()); ++rcIndex)
+ {
+ ui->cbxRateControlMode->addItem(rcModes[rcIndex].first, rcIndex);
}
//Update presets
{
ui->cbxPreset->setEnabled(true);
ui->cbxPreset->clear();
- ui->cbxPreset->addItem(QString::fromLatin1(OptionsModel::TUNING_UNSPECIFIED));
+ ui->cbxPreset->addItem(QString::fromLatin1(OptionsModel::SETTING_UNSPECIFIED));
ui->cbxPreset->addItems(presets);
}
{
ui->cbxTuning->setEnabled(true);
ui->cbxTuning->clear();
- ui->cbxTuning->addItem(QString::fromLatin1(OptionsModel::TUNING_UNSPECIFIED));
+ ui->cbxTuning->addItem(QString::fromLatin1(OptionsModel::SETTING_UNSPECIFIED));
ui->cbxTuning->addItems(tunings);
}
const AbstractEncoderInfo &encoderInfo = EncoderFactory::getEncoderInfo(encType);
//Update encoder profiles
- const QStringList profiles = encoderInfo.getProfiles(static_cast<OptionsModel::EncVariant>(ui->cbxEncoderVariant->itemData(index).toInt()));
+ const QStringList profiles = encoderInfo.getProfiles(ui->cbxEncoderVariant->itemData(index).toUInt());
if(profiles.empty())
{
ui->cbxProfile->setEnabled(false);
void AddJobDialog::modeIndexChanged(int index)
{
- ui->spinQuantizer->setEnabled(index == OptionsModel::RCMode_CRF || index == OptionsModel::RCMode_CQ);
- ui->spinBitrate ->setEnabled(index == OptionsModel::RCMode_ABR || index == OptionsModel::RCMode_2Pass);
+ const OptionsModel::EncType encType = static_cast<OptionsModel::EncType>(ui->cbxEncoderType->itemData(ui->cbxEncoderType->currentIndex()).toInt());
+ const AbstractEncoderInfo &encoderInfo = EncoderFactory::getEncoderInfo(encType);
+
+ //Update bitrate/quantizer boxes
+ const AbstractEncoderInfo::RCType rcType = encoderInfo.rcModeToType(ui->cbxRateControlMode->itemData(index).toUInt());
+ ui->spinQuantizer->setEnabled(rcType == AbstractEncoderInfo::RC_TYPE_QUANTIZER);
+ ui->spinBitrate ->setEnabled(rcType != AbstractEncoderInfo::RC_TYPE_QUANTIZER);
}
void AddJobDialog::accept(void)
{
+ //Get encoder info
+ const OptionsModel::EncType encType = static_cast<OptionsModel::EncType>(ui->cbxEncoderType->itemData(ui->cbxEncoderType->currentIndex()).toInt());
+ const AbstractEncoderInfo &encoderInfo = EncoderFactory::getEncoderInfo(encType);
+
//Check 64-Bit support
- if((ui->cbxEncoderArch->currentIndex() == OptionsModel::EncArch_x86_64) && (!m_sysinfo->getCPUFeatures(SysinfoModel::CPUFeatures_X64)))
+ if (encoderInfo.archToType(ui->cbxEncoderArch->itemData(ui->cbxEncoderArch->currentIndex()).toUInt()) == AbstractEncoderInfo::ARCH_TYPE_X64)
{
- QMessageBox::warning(this, tr("64-Bit unsupported!"), tr("<nobr>Sorry, this computer does <b>not</b> support 64-Bit encoders!</nobr>"));
- ui->cbxEncoderArch->setCurrentIndex(OptionsModel::EncArch_x86_32);
- return;
+ if (!m_sysinfo->getCPUFeatures(SysinfoModel::CPUFeatures_X64))
+ {
+ QMessageBox::warning(this, tr("64-Bit unsupported!"), tr("<nobr>Sorry, this computer does <b>not</b> support 64-Bit encoders!</nobr>"));
+ ui->cbxEncoderArch->setCurrentIndex(AbstractEncoderInfo::ARCH_TYPE_X86);
+ return;
+ }
}
//Selection complete?
return;
}
- //Get encoder info
- const OptionsModel::EncType encType = static_cast<OptionsModel::EncType>(ui->cbxEncoderType->itemData(ui->cbxEncoderType->currentIndex()).toInt());
- const AbstractEncoderInfo &encoderInfo = EncoderFactory::getEncoderInfo(encType);
-
- //Is selected RC mode supported?
- if(!encoderInfo.isRCModeSupported(static_cast<OptionsModel::RCMode>(ui->cbxRateControlMode->currentIndex())))
- {
- QMessageBox::warning(this, tr("Bad RC Mode!"), tr("<nobr>The selected RC mode is not supported by the selected encoder!</nobr>"));
- for(int i = 0; i < ui->cbxRateControlMode->count(); i++)
- {
- if(encoderInfo.isRCModeSupported(static_cast<OptionsModel::RCMode>(i)))
- {
- ui->cbxRateControlMode->setCurrentIndex(i);
- break;
- }
- }
- return;
- }
-
//Is the type of the source file supported?
const int sourceType = MediaInfo::analyze(sourceFile.canonicalFilePath());
if(sourceType == MediaInfo::FILETYPE_AVISYNTH)
}
else if(sourceType == MediaInfo::FILETYPE_VAPOURSYNTH)
{
- if(!m_sysinfo->hasAvisynth())
+ if(!m_sysinfo->hasVapourSynth())
{
if(QMessageBox::warning(this, tr("VapurSynth unsupported!"), tr("<nobr>A VapourSynth script was selected as input, although VapourSynth is <b>not/<b> available!</nobr>"), tr("Abort"), tr("Ignore (at your own risk!)")) != 1)
{
void AddJobDialog::updateComboBox(QComboBox *const cbox, const int &data)
{
int index = 0;
+ if (QAbstractItemModel *model = cbox->model())
+ {
+ for (int i = 0; i < cbox->model()->rowCount(); i++)
+ {
+ if (cbox->itemData(i).toInt() == data)
+ {
+ index = i;
+ break;
+ }
+ }
+ }
+ cbox->setCurrentIndex(index);
+}
+
+void AddJobDialog::updateComboBox(QComboBox *const cbox, const quint32 &data)
+{
+ int index = 0;
if(QAbstractItemModel *model = cbox->model())
{
for(int i = 0; i < cbox->model()->rowCount(); i++)
{
- if(model->itemData(model->index(i, 0, QModelIndex())).value(Qt::UserRole).toInt() == index)
+ if(cbox->itemData(i).toUInt() == data)
{
index = i;
break;
void AddJobDialog::restoreOptions(const OptionsModel *options)
{
- //Ignore config changes while restoring template!
- m_monitorConfigChanges = false;
+ DisableHelperRAII disable(&m_monitorConfigChanges);
updateComboBox(ui->cbxEncoderType, options->encType());
updateComboBox(ui->cbxEncoderArch, options->encArch());
ui->editCustomX264Params ->setText(options->customEncParams());
ui->editCustomAvs2YUVParams->setText(options->customAvs2YUV());
-
- //Force UI update
- encoderIndexChanged(ui->cbxEncoderType->currentIndex());
-
- //Make sure we will monitor config changes again!
- m_monitorConfigChanges = true;
}
void AddJobDialog::saveOptions(OptionsModel *options)
{
- options->setEncType (static_cast<OptionsModel::EncType> (ui->cbxEncoderType ->itemData(ui->cbxEncoderType ->currentIndex()).toInt()));
- options->setEncArch (static_cast<OptionsModel::EncArch> (ui->cbxEncoderArch ->itemData(ui->cbxEncoderArch ->currentIndex()).toInt()));
- options->setEncVariant(static_cast<OptionsModel::EncVariant>(ui->cbxEncoderVariant ->itemData(ui->cbxEncoderVariant ->currentIndex()).toInt()));
- options->setRCMode (static_cast<OptionsModel::RCMode> (ui->cbxRateControlMode->itemData(ui->cbxRateControlMode->currentIndex()).toInt()));
+ options->setEncType(static_cast<OptionsModel::EncType>(ui->cbxEncoderType->itemData(ui->cbxEncoderType->currentIndex()).toInt()));
+
+ options->setEncArch (ui->cbxEncoderArch ->itemData(ui->cbxEncoderArch ->currentIndex()).toUInt());
+ options->setEncVariant(ui->cbxEncoderVariant ->itemData(ui->cbxEncoderVariant ->currentIndex()).toUInt());
+ options->setRCMode (ui->cbxRateControlMode->itemData(ui->cbxRateControlMode->currentIndex()).toUInt());
options->setQuantizer(ui->spinQuantizer->value());
- options->setBitrate(ui->spinBitrate->value());
+ options->setBitrate (ui->spinBitrate ->value());
options->setPreset (ui->cbxPreset ->model()->data(ui->cbxPreset ->model()->index(ui->cbxPreset ->currentIndex(), 0)).toString());
options->setTune (ui->cbxTuning ->model()->data(ui->cbxTuning ->model()->index(ui->cbxTuning ->currentIndex(), 0)).toString());
options->setProfile(ui->cbxProfile->model()->data(ui->cbxProfile->model()->index(ui->cbxProfile->currentIndex(), 0)).toString());
- options->setCustomEncParams(ui->editCustomX264Params->hasAcceptableInput() ? ui->editCustomX264Params->text().simplified() : QString());
+ options->setCustomEncParams(ui->editCustomX264Params->hasAcceptableInput() ? ui->editCustomX264Params->text().simplified() : QString());
options->setCustomAvs2YUV(ui->editCustomAvs2YUVParams->hasAcceptableInput() ? ui->editCustomAvs2YUVParams->text().simplified() : QString());
}