///////////////////////////////////////////////////////////////////////////////
// Simple x264 Launcher
-// Copyright (C) 2004-2016 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"
};
///////////////////////////////////////////////////////////////////////////////
-// Validator
-///////////////////////////////////////////////////////////////////////////////
-
-class StringValidator : public QValidator
-{
-public:
- StringValidator(QLabel *notifier, QLabel *icon)
- :
- m_notifier(notifier), m_icon(icon)
- {
- 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 QStringList &input, const char *const params[], const bool &doubleMinus) const
- {
- for(QStringList::ConstIterator iter = input.constBegin(); iter != input.constEnd(); iter++)
- {
- for(size_t k = 0; params[k]; k++)
- {
- const QString param = QLatin1String(params[k]);
- const QString prefix = ((param.length() > 1) && doubleMinus) ? QLatin1String("--") : QLatin1String("-");
- if(iter->compare(QString("%1%2").arg(prefix, param), Qt::CaseInsensitive) == 0)
- {
- if(m_notifier)
- {
- m_notifier->setText(tr("Forbidden parameter: %1").arg(*iter));
- }
- return true;
- }
- }
- if(iter->startsWith("--", Qt::CaseInsensitive))
- {
- for(int i = 2; i < iter->length(); i++)
- {
- if((iter->at(i) == QLatin1Char('=')) && (i > 2) && (i + 1 < iter->length()))
- {
- break; /*to allow "--param=value" format*/
- }
- if((!iter->at(i).isLetter()) && ((iter->at(i) != QLatin1Char('-')) || (i < 3)))
- {
- if(m_notifier)
- {
- m_notifier->setText(tr("Invalid string: %1").arg(*iter));
- }
- return true;
- }
- }
- }
- }
-
- return false;
- }
-
- bool checkPrefix(const QStringList &input, const bool &doubleMinus) const
- {
- for(QStringList::ConstIterator iter = input.constBegin(); iter != input.constEnd(); iter++)
- {
- static const char *const c[3] = { "--", "-", NULL };
- for(size_t i = 0; c[i]; i++)
- {
- const QString prefix = QString::fromLatin1(c[i]);
- if(iter->compare(prefix, Qt::CaseInsensitive) == 0)
- {
- if(m_notifier)
- {
- m_notifier->setText(tr("Invalid parameter: %1").arg(prefix));
- }
- return true;
- }
- }
- if
- (
- ((!doubleMinus) && iter->startsWith("--", Qt::CaseInsensitive)) ||
- (doubleMinus && iter->startsWith("-", Qt::CaseInsensitive) && (!iter->startsWith("--", Qt::CaseInsensitive)) && (iter->length() > 2) && (!iter->at(1).isDigit())) ||
- (doubleMinus && iter->startsWith("--", Qt::CaseInsensitive) && (iter->length() < 4))
- )
- {
- if(m_notifier)
- {
- m_notifier->setText(tr("Invalid syntax: %1").arg(*iter));
- }
- return true;
- }
- }
- return false;
- }
-
- bool checkCharacters(const QStringList &input) const
- {
- static const char c[] = {'*', '?', '<', '>', '|', NULL};
-
- for(QStringList::ConstIterator iter = input.constBegin(); iter != input.constEnd(); iter++)
- {
- for(size_t i = 0; c[i]; i++)
- {
- if(iter->indexOf(QLatin1Char(c[i])) >= 0)
- {
- if(m_notifier)
- {
- m_notifier->setText(tr("Invalid character: '%1'").arg(QLatin1Char(c[i])));
- }
- 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;
- }
-};
-
-class StringValidatorX264 : public StringValidator
-{
-public:
- StringValidatorX264(QLabel *notifier, QLabel *icon) : StringValidator(notifier, icon) {}
-
- virtual State validate(QString &input, int &pos) const
- {
- static const char *const params[] = {"B", "o", "h", "p", "q", /*"fps", "frames",*/ "preset", "tune", "profile",
- "stdin", "crf", "bitrate", "qp", "pass", "stats", "output", "help", "quiet", NULL};
-
- const QString commandLine = input.trimmed();
- const QStringList tokens = commandLine.isEmpty() ? QStringList() : MUtils::OS::crack_command_line(commandLine);
-
- const bool invalid = checkCharacters(tokens) || checkPrefix(tokens, true) || checkParam(tokens, params, 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 *const params[] = {"o", "frames", "seek", "raw", "hfyu", "slave", NULL};
-
- const QString commandLine = input.trimmed();
- const QStringList tokens = commandLine.isEmpty() ? QStringList() : MUtils::OS::crack_command_line(commandLine);
-
- const bool invalid = checkCharacters(tokens) || checkPrefix(tokens, false) || checkParam(tokens, params, false);
- return setStatus(invalid, "Avs2YUV") ? QValidator::Intermediate : QValidator::Acceptable;
- }
-};
-
-///////////////////////////////////////////////////////////////////////////////
// Constructor & Destructor
///////////////////////////////////////////////////////////////////////////////
ui->cbxEncoderType->addItem(tr("x265 (HEVC)"), OptionsModel::EncType_X265);
ui->cbxEncoderType->addItem(tr("NVEncC"), OptionsModel::EncType_NVEnc);
- //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);
-
//Init combobox items
ui->cbxTuning ->addItem(QString::fromLatin1(OptionsModel::SETTING_UNSPECIFIED));
ui->cbxProfile->addItem(QString::fromLatin1(OptionsModel::PROFILE_UNRESTRICTED));
//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
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
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)
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(cbox->itemData(i).toInt() == data)
+ if(cbox->itemData(i).toUInt() == data)
{
index = i;
break;
void AddJobDialog::restoreOptions(const OptionsModel *options)
{
- DisableHelperRAII disbale(&m_monitorConfigChanges);
+ DisableHelperRAII disable(&m_monitorConfigChanges);
updateComboBox(ui->cbxEncoderType, options->encType());
updateComboBox(ui->cbxEncoderArch, options->encArch());
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());
}