From 5e1077f72b3972f8cce88d685b53fd86b0e62ac7 Mon Sep 17 00:00:00 2001 From: CrSjimo Date: Fri, 4 Oct 2024 22:10:22 +0800 Subject: [PATCH] update audio plugin --- .../audio/exporter/audioexporter.cpp | 153 ++++- .../audio/exporter/audioexporter.h | 14 + .../audio/exporter/audioexporter_p.h | 2 + .../internal/addon/projectaddon.cpp | 9 + .../audioplugin/internal/addon/projectaddon.h | 6 + .../audioplugin/internal/audioplugin.cpp | 3 - .../internal/dialogs/audioexportdialog.cpp | 540 +++++++++++++++++- .../internal/dialogs/audioexportdialog.h | 31 +- .../internal/settings/audioexportpage.cpp | 33 +- .../internal/utils/audiosettings.cpp | 4 +- .../internal/utils/audiosettings.h | 2 + 11 files changed, 753 insertions(+), 44 deletions(-) diff --git a/src/plugins/audioplugin/audio/exporter/audioexporter.cpp b/src/plugins/audioplugin/audio/exporter/audioexporter.cpp index 72bd870..5c4b52a 100644 --- a/src/plugins/audioplugin/audio/exporter/audioexporter.cpp +++ b/src/plugins/audioplugin/audio/exporter/audioexporter.cpp @@ -1,6 +1,7 @@ #include "audioexporter.h" #include "audioexporter_p.h" +#include #include #include #include @@ -51,6 +52,41 @@ namespace Audio { void AudioExporterConfig::setFormatMono(bool a_) { d->formatMono = a_; } + QStringList AudioExporterConfig::formatOptionsOfType(FileType type) { + switch (type) { + case FT_Wav: + return { + QApplication::translate("Audio::AudioExporterConfig", + "32-bit float (IEEE 754)"), + QApplication::translate("Audio::AudioExporterConfig", "24-bit PCM"), + QApplication::translate("Audio::AudioExporterConfig", "16-bit PCM"), + QApplication::translate("Audio::AudioExporterConfig", "Unsigned 8-bit PCM"), + }; + case FT_Flac: + return { + QApplication::translate("Audio::AudioExporterConfig", "24-bit PCM"), + QApplication::translate("Audio::AudioExporterConfig", "16-bit PCM"), + QApplication::translate("Audio::AudioExporterConfig", "8-bit PCM"), + }; + default: + return {}; + } + } + + QString AudioExporterConfig::extensionOfType(FileType type) { + switch (type) { + case FT_Wav: + return QStringLiteral("wav"); + case FT_Flac: + return QStringLiteral("flac"); + case FT_OggVorbis: + return QStringLiteral("ogg"); + case FT_Mp3: + return QStringLiteral("mp3"); + } + return {}; + } + int AudioExporterConfig::formatOption() const { return d->formatOption; } @@ -132,6 +168,19 @@ namespace Audio { config.d->timeRange = static_cast(map.value("timeRange").toInt()); return config; } + bool AudioExporterConfig::operator==(const AudioExporterConfig &other) const { + return d->fileName == other.d->fileName + && d->fileDirectory == other.d->fileDirectory + && d->fileType == other.d->fileType + && d->formatMono == other.d->formatMono + && d->formatOption == other.d->formatOption + && d->formatQuality == other.d->formatQuality + && d->formatSampleRate == other.d->formatSampleRate + && d->mixingOption == other.d->mixingOption + && d->isMuteSoloEnabled == other.d->isMuteSoloEnabled + && d->sourceOption == other.d->sourceOption + && d->timeRange == other.d->timeRange; + } QString AudioExporterPrivate::projectName() const { // project file's base name @@ -173,7 +222,7 @@ namespace Audio { if (templateName == "projectName") { replacedText = projectName(); } else if (templateName == "sampleRate") { - replacedText = QString::number(config.formatSampleRate()); + replacedText = QString::number(config.formatSampleRate()).replace('.', '_'); } else if (templateName == "today") { replacedText = QDate::currentDate().toString("yyyyMMdd"); } else if (templateName == "$") { @@ -183,6 +232,8 @@ namespace Audio { replacedText = trackName; } else if (templateName == "trackIndex") { replacedText = QString::number(trackIndex + 1); + } else { + allTemplatesMatch = false; } } else { allTemplatesMatch = false; @@ -195,19 +246,64 @@ namespace Audio { templateString = result; return allTemplatesMatch; } + + int AudioExporterPrivate::calculateFormat() const { + int format = 0; + switch (config.fileType()) { + case AudioExporterConfig::FT_Wav: + format |= talcs::AudioFormatIO::WAV; + switch (config.formatOption()) { + case 0: + format |= talcs::AudioFormatIO::FLOAT; + return format; + case 1: + format |= talcs::AudioFormatIO::PCM_24; + return format; + case 2: + format |= talcs::AudioFormatIO::PCM_16; + return format; + case 3: + format |= talcs::AudioFormatIO::PCM_U8; + return format; + } + break; + case AudioExporterConfig::FT_Flac: + format |= talcs::AudioFormatIO::FLAC; + switch (config.formatOption()) { + case 0: + format |= talcs::AudioFormatIO::PCM_24; + return format; + case 1: + format |= talcs::AudioFormatIO::PCM_16; + return format; + case 2: + format |= talcs::AudioFormatIO::PCM_S8; + return format; + } + break; + case AudioExporterConfig::FT_OggVorbis: + format |= (talcs::AudioFormatIO::OGG | talcs::AudioFormatIO::VORBIS); + return format; + case AudioExporterConfig::FT_Mp3: + format |= (talcs::AudioFormatIO::MPEG | talcs::AudioFormatIO::MPEG_LAYER_III); + return format; + } + return 0; + } + void AudioExporterPrivate::updateFileListAndWarnings() { warning = {}; if (config.fileType() == AudioExporterConfig::FT_Mp3 || config.fileType() == AudioExporterConfig::FT_OggVorbis) warning |= AudioExporter::W_LossyFormat; fileList.clear(); - if (config.sourceOption() == AudioExporterConfig::SO_All) { + if (config.mixingOption() == AudioExporterConfig::MO_Mixed) { auto calculatedFileName = config.fileName(); if (!calculateTemplate(calculatedFileName)) warning |= AudioExporter::W_UnrecognizedTemplate; - auto fileInfo = QFileInfo(QDir(projectDirectory()).absoluteFilePath(calculatedFileName)); + auto fileInfo = QFileInfo(QDir(QDir(projectDirectory()).absoluteFilePath(config.fileDirectory())).absoluteFilePath(calculatedFileName)); if (fileInfo.exists()) warning |= AudioExporter::W_WillOverwrite; - fileList.append(fileInfo.canonicalFilePath()); + fileList.append(fileInfo.absoluteFilePath()); } else { if (config.source().isEmpty()) warning |= AudioExporter::W_NoFile; @@ -216,13 +312,13 @@ namespace Audio { auto calculatedFileName = config.fileName(); if (!calculateTemplate(calculatedFileName, trackName(index), index)) warning |= AudioExporter::W_UnrecognizedTemplate; - auto fileInfo = QFileInfo(QDir(projectDirectory()).absoluteFilePath(calculatedFileName)); + auto fileInfo = QFileInfo(QDir(QDir(projectDirectory()).absoluteFilePath(config.fileDirectory())).absoluteFilePath(calculatedFileName)); if (fileInfo.exists()) warning |= AudioExporter::W_WillOverwrite; - if (fileSet.contains(fileInfo.canonicalFilePath())) + if (fileSet.contains(fileInfo.absoluteFilePath())) warning |= AudioExporter::W_DuplicatedFile; - fileSet.insert(fileInfo.canonicalFilePath()); - fileList.append(fileInfo.canonicalFilePath()); + fileSet.insert(fileInfo.absoluteFilePath()); + fileList.append(fileInfo.absoluteFilePath()); } } } @@ -234,6 +330,11 @@ namespace Audio { } AudioExporter::~AudioExporter() = default; + Core::IProjectWindow *AudioExporter::windowHandle() const { + Q_D(const AudioExporter); + return d->windowHandle; + } + QStringList AudioExporter::presets() { return AudioSettings::audioExporterPresets().toObject().keys(); } @@ -261,7 +362,7 @@ namespace Audio { {"formatOption", 0}, {"formatQuality", 100}, {"formatSampleRate", 48000}, - {"mixingOption", AudioExporterConfig::MO_Separated}, + {"mixingOption", AudioExporterConfig::MO_SeparatedThruMaster}, {"isMuteSoloEnabled", true}, {"sourceOption", AudioExporterConfig::SO_All}, {"source", {}}, @@ -289,7 +390,7 @@ namespace Audio { {"formatOption", 0}, {"formatQuality", 100}, {"formatSampleRate", 48000}, - {"mixingOption", AudioExporterConfig::MO_Separated}, + {"mixingOption", AudioExporterConfig::MO_SeparatedThruMaster}, {"isMuteSoloEnabled", true}, {"sourceOption", AudioExporterConfig::SO_All}, {"source", {}}, @@ -317,7 +418,7 @@ namespace Audio { {"formatOption", 0}, {"formatQuality", 100}, {"formatSampleRate", 48000}, - {"mixingOption", AudioExporterConfig::MO_Separated}, + {"mixingOption", AudioExporterConfig::MO_SeparatedThruMaster}, {"isMuteSoloEnabled", true}, {"sourceOption", AudioExporterConfig::SO_All}, {"source", {}}, @@ -382,13 +483,13 @@ namespace Audio { list.append(tr("The files to be exported contain files with duplicate names. Please check if the file name template is unique for each source.")); } if (warning & W_WillOverwrite) { - list.append(tr("The files to be exported contain files with the same name as existing files.")); + list.append(tr("The files to be exported contain files with the same name as existing files. If continue, the existing files will be overwritten.")); } if (warning & W_UnrecognizedTemplate) { list.append(tr("Unrecognized file name template. Please check the syntax of the file name template.")); } if (warning & W_LossyFormat) { - list.append(tr("Currently selected file type is a lossy format. Please use WAV or FLAC format to avoid loss of sound quality.")); + list.append(tr("The currently selected file type is a lossy format. To avoid loss of sound quality, please use WAV or FLAC format.")); } return list; } @@ -419,18 +520,18 @@ namespace Audio { io.setStream(file); io.setSampleRate(config.formatSampleRate()); io.setChannelCount(config.formatMono() ? 1 : 2); - io.setFormat(talcs::AudioFormatIO::WAV | talcs::AudioFormatIO::FLOAT); // TODO calculte AudioFormatIO format from config - io.setCompressionLevel(0.01 * (100 - config.formatQuality())); + io.setFormat(d->calculateFormat()); if (!io.open(talcs::AbstractAudioFormatIO::Write)) { setErrorString(tr("Format not supported: %1").arg(io.errorString())); return R_Fail; } + io.setCompressionLevel(0.01 * (100 - config.formatQuality())); } // create and configure talcs::DspxProjectAudioExporter talcs::DspxProjectAudioExporter exporter(projectContext); auto cleanup = [=](void *) {d->currentExporter = nullptr;}; - std::unique_ptr _1(nullptr, cleanup); + std::unique_ptr _1(this, cleanup); d->currentExporter = &exporter; exporter.setMonoChannel(config.formatMono()); exporter.setThruMaster(config.mixingOption() == AudioExporterConfig::MO_SeparatedThruMaster); @@ -471,16 +572,26 @@ namespace Audio { if (!projectContext->preMixer()->open(currentBufferSize, currentSampleRate)) qDebug() << "AudioExporter: Cannot reopen pre-mixer after exported"; }; - std::unique_ptr _2(nullptr, reopenMixer); + std::unique_ptr _2(this, reopenMixer); if (!projectContext->preMixer()->open(1024, config.formatSampleRate())) { // TODO let user configure buffer size in settings setErrorString(tr("Cannot start audio exporting")); return R_Fail; } // call listeners + QList listenerToCallFinishList; + auto callFinish = [&](void *) { + for (auto listener : listenerToCallFinishList) { + listener->willFinishCallback(this); + } + }; + std::unique_ptr _3(this, callFinish); + // Note: order of destruction: call AudioExporterListener::willFinish after mixer reopened + std::unique_ptr _4 = std::move(_2); for (auto listener : m_listeners) { if (!listener->willStartCallback(this)) return R_Fail; + listenerToCallFinishList.prepend(listener); } // start exporting @@ -491,9 +602,9 @@ namespace Audio { emit clippingDetected(sourceIndexMap.value(track)); }); auto ret = exporter.exec(); - if (ret & talcs::DspxProjectAudioExporter::OK) + if (ret == talcs::DspxProjectAudioExporter::OK) return R_OK; - if (ret & talcs::DspxProjectAudioExporter::Interrupted) + if (ret == talcs::DspxProjectAudioExporter::Interrupted) return R_Abort; if (errorString().isEmpty()) @@ -509,4 +620,8 @@ namespace Audio { setErrorString(message.isEmpty() ? tr("Unknown error") : message); d->currentExporter->interrupt(isFail); } + + void AudioExporter::addWarning(const QString &message, int sourceIndex) { + emit warningAdded(message, sourceIndex); + } } // Audio diff --git a/src/plugins/audioplugin/audio/exporter/audioexporter.h b/src/plugins/audioplugin/audio/exporter/audioexporter.h index 4fb25af..828a772 100644 --- a/src/plugins/audioplugin/audio/exporter/audioexporter.h +++ b/src/plugins/audioplugin/audio/exporter/audioexporter.h @@ -11,6 +11,12 @@ namespace Core { } namespace Audio { + + + namespace Internal { + class AudioExportDialog; + } + class AudioExporter; class AudioExporterConfigData; @@ -39,6 +45,9 @@ namespace Audio { bool formatMono() const; void setFormatMono(bool); + [[nodiscard]] static QStringList formatOptionsOfType(FileType type); + [[nodiscard]] static QString extensionOfType(FileType type); + int formatOption() const; void setFormatOption(int); @@ -80,6 +89,8 @@ namespace Audio { QVariantMap toVariantMap() const; [[nodiscard]] static AudioExporterConfig fromVariantMap(const QVariantMap &map); + bool operator==(const AudioExporterConfig &other) const; + private: QSharedDataPointer d; }; @@ -93,6 +104,7 @@ namespace Audio { class AudioExporter : public QObject, public talcs::ErrorStringProvider { Q_OBJECT Q_DECLARE_PRIVATE(AudioExporter) + friend class Internal::AudioExportDialog; public: explicit AudioExporter(Core::IProjectWindow *window, QObject *parent = nullptr); @@ -132,10 +144,12 @@ namespace Audio { Result exec(); void cancel(bool isFail = false, const QString &message = {}); + void addWarning(const QString &message, int sourceIndex = -1); signals: void progressChanged(double progressRatio, int sourceIndex); void clippingDetected(int sourceIndex); + void warningAdded(const QString &message, int sourceIndex); private: QScopedPointer d_ptr; diff --git a/src/plugins/audioplugin/audio/exporter/audioexporter_p.h b/src/plugins/audioplugin/audio/exporter/audioexporter_p.h index 80a6249..fd5d4f9 100644 --- a/src/plugins/audioplugin/audio/exporter/audioexporter_p.h +++ b/src/plugins/audioplugin/audio/exporter/audioexporter_p.h @@ -45,6 +45,8 @@ namespace Audio { bool calculateTemplate(QString &templateString) const; bool calculateTemplate(QString &templateString, const QString &trackName, int trackIndex) const; + int calculateFormat() const; + AudioExporter::Warning warning; QStringList fileList; void updateFileListAndWarnings(); diff --git a/src/plugins/audioplugin/internal/addon/projectaddon.cpp b/src/plugins/audioplugin/internal/addon/projectaddon.cpp index f6346ad..2415843 100644 --- a/src/plugins/audioplugin/internal/addon/projectaddon.cpp +++ b/src/plugins/audioplugin/internal/addon/projectaddon.cpp @@ -83,4 +83,13 @@ namespace Audio::Internal { m_failedAudioClipsToAlert.clear(); return ret; } + void ProjectAddOn::setData(const QString &key, const QVariant &value) { + m_dataDict.insert(key, value); + } + QVariant ProjectAddOn::data(const QString &key) const { + return m_dataDict.value(key); + } + bool ProjectAddOn::hasData(const QString &key) const { + return m_dataDict.contains(key); + } } \ No newline at end of file diff --git a/src/plugins/audioplugin/internal/addon/projectaddon.h b/src/plugins/audioplugin/internal/addon/projectaddon.h index 2241bcb..6246707 100644 --- a/src/plugins/audioplugin/internal/addon/projectaddon.h +++ b/src/plugins/audioplugin/internal/addon/projectaddon.h @@ -50,6 +50,10 @@ namespace Audio::Internal { void addFailedAudioClipToAlert(QDspx::AudioClipEntity *entity); QList takeFailedAudioClipsToAlert(); + void setData(const QString &key, const QVariant &value); + QVariant data(const QString &key) const; + bool hasData(const QString &key) const; + private: AudioContextInterface *m_audioContextInterface; talcs::DspxProjectContext *m_projectContext; @@ -57,6 +61,8 @@ namespace Audio::Internal { QHash m_audioClipsToOpenFile; QList m_failedAudioClipsToAlert; + + QHash m_dataDict; }; } diff --git a/src/plugins/audioplugin/internal/audioplugin.cpp b/src/plugins/audioplugin/internal/audioplugin.cpp index d2c9370..71b6cd2 100644 --- a/src/plugins/audioplugin/internal/audioplugin.cpp +++ b/src/plugins/audioplugin/internal/audioplugin.cpp @@ -110,9 +110,6 @@ namespace Audio::Internal { new DeviceTester(iAudio->outputSystemInterface(true), iAudio->outputSystemInterface(true)); new DeviceTester(iAudio->outputSystemInterface(false), iAudio->outputSystemInterface(false)); - AudioExportDialog dlg; - dlg.exec(); - return true; } void AudioPlugin::extensionsInitialized() { diff --git a/src/plugins/audioplugin/internal/dialogs/audioexportdialog.cpp b/src/plugins/audioplugin/internal/dialogs/audioexportdialog.cpp index bb7739c..7cca463 100644 --- a/src/plugins/audioplugin/internal/dialogs/audioexportdialog.cpp +++ b/src/plugins/audioplugin/internal/dialogs/audioexportdialog.cpp @@ -1,7 +1,5 @@ #include "audioexportdialog.h" -#include - #include #include @@ -15,20 +13,42 @@ #include #include #include +#include +#include #include +#include #include #include #include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include namespace Audio::Internal { - AudioExportDialog::AudioExportDialog(QWidget *parent) : QDialog(parent) { + AudioExportDialog::AudioExportDialog(Core::IProjectWindow *windowHandle, QWidget *parent) : QDialog(parent), m_audioExporter(new AudioExporter(windowHandle, this)) { setWindowTitle(tr("Export Audio")); setWindowFlag(Qt::WindowContextHelpButtonHint, false); auto mainLayout = new QVBoxLayout; - + auto presetLayout = new QFormLayout; auto presetOptionLayout = new QHBoxLayout; m_presetComboBox = new QComboBox; + for (const auto &[presetName, presetConfig] : AudioExporter::predefinedPresets()) { + m_presetComboBox->addItem(presetName); + } + for (const auto &presetName : AudioExporter::presets()) { + m_presetComboBox->addItem(presetName, presetName); + } presetOptionLayout->addWidget(m_presetComboBox, 1); auto presetSaveAsButton = new QPushButton(tr("Save &As")); presetOptionLayout->addWidget(presetSaveAsButton); @@ -97,6 +117,8 @@ namespace Audio::Internal { auto nameLabel = new QLabel(tr("&Name")); nameLabel->setBuddy(m_fileNameEdit); pathLayout->addRow(nameLabel, fileNameLayout); + m_fileNamePreviewLabel = new QLabel; + pathLayout->addWidget(m_fileNamePreviewLabel); m_fileDirectoryEdit = new QLineEdit; m_fileDirectoryEdit->setPlaceholderText(tr("(Project directory)")); pathLayout->addRow(tr("Dire&ctory"), m_fileDirectoryEdit); @@ -129,9 +151,11 @@ namespace Audio::Internal { m_formatSampleRateComboBox = new QComboBox; m_formatSampleRateComboBox->setEditable(true); m_formatSampleRateComboBox->setValidator(new QDoubleValidator(0.01, std::numeric_limits::max(), 2)); - m_formatSampleRateComboBox->addItems({"8000", "11025", "12000", "16000", "22050", "24000", - "32000", "44100", "48000", "64000", "88200", "96000", - "128000", "176400", "192000", "256000", "352800", "384000"}); + QLocale locale; + locale.setNumberOptions(QLocale::OmitGroupSeparator); + m_formatSampleRateComboBox->addItems({locale.toString(8000), locale.toString(11025), locale.toString(12000), locale.toString(16000), locale.toString(22050), locale.toString(24000), + locale.toString(32000), locale.toString(44100), locale.toString(48000), locale.toString(64000), locale.toString(88200), locale.toString(96000), + locale.toString(128000), locale.toString(176400), locale.toString(192000), locale.toString(256000), locale.toString(352800), locale.toString(384000)}); formatLayout->addRow(tr("&Sample rate"), m_formatSampleRateComboBox); formatGroupBox->setLayout(formatLayout); leftLayout->addWidget(formatGroupBox); @@ -146,7 +170,7 @@ namespace Audio::Internal { }); connect(m_mixingOptionComboBox, QOverload::of(&QComboBox::currentIndexChanged), fileNameTemplateTrackNameAction, &QAction::setEnabled); connect(m_mixingOptionComboBox, QOverload::of(&QComboBox::currentIndexChanged), fileNameTemplateTrackIndexAction, &QAction::setEnabled); - mixingLayout->addRow(tr("&Mixing Option"), m_mixingOptionComboBox); + mixingLayout->addRow(tr("&Mixing option"), m_mixingOptionComboBox); m_enableMuteSoloCheckBox = new QCheckBox(tr("Enable m&ute/solo")); m_enableMuteSoloCheckBox->setChecked(true); mixingLayout->addRow(m_enableMuteSoloCheckBox); @@ -158,7 +182,22 @@ namespace Audio::Internal { }); mixingLayout->addRow(tr("&Source"), m_sourceComboBox); m_sourceListWidget = new QListWidget; - // TODO add tracks + m_sourceListWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); + for (const auto &trackName : projectTrackList()) { + auto item = new QListWidgetItem(trackName); + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); + item->setCheckState(Qt::Unchecked); + m_sourceListWidget->addItem(item); + } + connect(m_sourceListWidget, &QListWidget::itemChanged, this, [=](QListWidgetItem *item) { + item->setSelected(item->checkState() == Qt::Checked); + }); + connect(m_sourceListWidget, &QListWidget::itemSelectionChanged, this, [=] { + for (int i = 0; i < m_sourceListWidget->count(); i++) { + auto item = m_sourceListWidget->item(i); + item->setCheckState(item->isSelected() ? Qt::Checked : Qt::Unchecked); + } + }); mixingLayout->addRow(m_sourceListWidget); mixingGroupBox->setLayout(mixingLayout); @@ -208,7 +247,488 @@ namespace Audio::Internal { setLayout(mainLayout); resize(600, 800); + + connect(m_fileNameEdit, &QLineEdit::textChanged, this, &AudioExportDialog::updateConfig); + connect(m_fileDirectoryEdit, &QLineEdit::textChanged, this, &AudioExportDialog::updateConfig); + connect(m_fileTypeComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, [=](int index) { + QFileInfo fileInfo(m_fileNameEdit->text()); + m_fileNameEdit->setText(fileInfo.baseName() + "." + AudioExporterConfig::extensionOfType(static_cast(index))); + m_formatOptionComboBox->clear(); + auto options = AudioExporterConfig::formatOptionsOfType(static_cast(index)); + if (options.isEmpty()) { + m_formatOptionComboBox->setDisabled(true); + } else { + m_formatOptionComboBox->setDisabled(false); + m_formatOptionComboBox->addItems(options); + m_formatOptionComboBox->setCurrentIndex(0); + } + if (index == AudioExporterConfig::FT_Wav) { + m_vbrSlider->setValue(100); + m_vbrSlider->setDisabled(true); + vbrSpinBox->setDisabled(true); + } else { + m_vbrSlider->setDisabled(false); + vbrSpinBox->setDisabled(false); + } + updateConfig(); + }); + connect(m_formatMonoComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &AudioExportDialog::updateConfig); + connect(m_formatOptionComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &AudioExportDialog::updateConfig); + connect(m_vbrSlider, &QSlider::valueChanged, this, &AudioExportDialog::updateConfig); + connect(m_formatSampleRateComboBox, &QComboBox::currentTextChanged, this, &AudioExportDialog::updateConfig); + connect(m_sourceComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, [=](int index) { + if (index == AudioExporterConfig::SO_All) { + m_sourceListWidget->setDisabled(false); + m_sourceListWidget->selectAll(); + m_sourceListWidget->setDisabled(true); + } else if (index == AudioExporterConfig::SO_Selected) { + m_sourceListWidget->setDisabled(false); + m_sourceListWidget->clearSelection(); + for (auto index : m_audioExporter->d_func()->selectedSources()) { + m_sourceListWidget->item(index)->setSelected(true); + } + m_sourceListWidget->setDisabled(true); + } else { + m_sourceListWidget->setDisabled(false); + } + updateConfig(); + }); + connect(m_sourceListWidget, &QListWidget::itemSelectionChanged, this, &AudioExportDialog::updateConfig); + connect(m_mixingOptionComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, [=](int index) { + if (index == AudioExporterConfig::MO_Mixed) { + QFileInfo fileInfo(m_fileNameEdit->text()); + auto basename = fileInfo.baseName(); + auto suffix = fileInfo.completeSuffix(); + if (basename.endsWith("_${trackIndex}_${trackName}")) { + basename = basename.chopped(27); + } + if (suffix.isEmpty()) { + suffix = AudioExporterConfig::extensionOfType(m_audioExporter->config().fileType()); + } + m_fileNameEdit->setText(basename + "." + suffix); + } else { + QFileInfo fileInfo(m_fileNameEdit->text()); + auto basename = fileInfo.baseName(); + auto suffix = fileInfo.completeSuffix(); + if (!basename.contains("${trackIndex}") && !basename.contains("${trackName}")) { + basename += "_${trackIndex}_${trackName}"; + } + if (suffix.isEmpty()) { + suffix = AudioExporterConfig::extensionOfType(m_audioExporter->config().fileType()); + } + m_fileNameEdit->setText(basename + "." + suffix); + } + updateConfig(); + }); + connect(m_enableMuteSoloCheckBox, &QAbstractButton::toggled, this, &AudioExportDialog::updateConfig); + connect(m_rangeSelectAllRadio, &QAbstractButton::toggled, this, &AudioExportDialog::updateConfig); + + connect(filePathBrowseButton, &QAbstractButton::clicked, this, &AudioExportDialog::browseFile); + connect(m_warningButton, &QAbstractButton::clicked, this, &AudioExportDialog::showWarnings); + connect(dryRunButton, &QAbstractButton::clicked, this, &AudioExportDialog::showDryRunResult); + + connect(m_presetComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, [=](int index) { + auto data = m_presetComboBox->itemData(index); + auto config = data.isNull() ? AudioExporter::predefinedPresets().at(index).second : AudioExporter::preset(data.toString()); + m_presetDeleteButton->setDisabled(data.isNull()); + m_audioExporter->setConfig(config); + updateView(); + }); + connect(presetSaveAsButton, &QAbstractButton::clicked, this, [=] { + QString result = m_presetComboBox->currentText(); + while (true) { + result = QInputDialog::getText(this, {}, tr("Preset name"), {}, result); + if (result.isEmpty()) + return; + if (AudioExporter::presets().contains(result)) { + if (QMessageBox::question(this, {}, tr("Preset \"%1\" already exists. Overwrite it?").arg(result)) == QMessageBox::Yes) + break; + } else { + break; + } + } + auto config = m_audioExporter->config(); + AudioExporter::addPreset(result, config); + [=] { + for (int i = 0; i < m_presetComboBox->count(); i++) { + if (m_presetComboBox->itemData(i).toString() == result) { + m_presetComboBox->setCurrentIndex(i); + emit m_presetComboBox->currentIndexChanged(i); + return; + } + } + m_presetComboBox->addItem(result, result); + m_presetComboBox->setCurrentIndex(m_presetComboBox->count() - 1); + }(); + }); + connect(m_presetDeleteButton, &QAbstractButton::clicked, this, [=] { + AudioExporter::removePreset(m_presetComboBox->currentData().toString()); + m_presetComboBox->removeItem(m_presetComboBox->currentIndex()); + }); + + emit m_fileTypeComboBox->currentIndexChanged(0); + emit m_sourceComboBox->currentIndexChanged(0); + emit m_mixingOptionComboBox->currentIndexChanged(0); + auto currentPresetKey = AudioSettings::audioExporterCurrentPreset(); + if (currentPresetKey.isString()) { + for (int i = 0; i < m_presetComboBox->count(); i++) { + if (m_presetComboBox->itemData(i).toString() == currentPresetKey.toString()) { + m_presetComboBox->setCurrentIndex(i); + break; + } + } + } else { + m_presetComboBox->setCurrentIndex(currentPresetKey.toInt()); + } + emit m_presetComboBox->currentIndexChanged(m_presetComboBox->currentIndex()); + if (hasTemporaryPreset()) { + restoreTemporaryPreset(); + updateView(); + } + + connect(exportButton, &QAbstractButton::clicked, this, &AudioExportDialog::runExport); + connect(cancelButton, &QAbstractButton::clicked, this, &QDialog::reject); + } AudioExportDialog::~AudioExportDialog() { } -} \ No newline at end of file + + QStringList AudioExportDialog::projectTrackList() const { + auto tracks = m_audioExporter->windowHandle()->doc()->dataModel().model()->tracks(); + QStringList list; + for (int i = 0; i < tracks->size(); i++) { + list.append(tracks->at(i)->trackName()); + } + return list; + } + + void AudioExportDialog::browseFile() { + QStringList filters = { + tr("WAV (*.wav)"), + tr("FLAC (*.flac)"), + tr("Ogg Vorbis (*.ogg)"), + tr("MP3 (*.mp3)"), + }; + QString selectedFilter = filters.at(m_fileTypeComboBox->currentIndex()); + auto path = + QFileDialog::getSaveFileName(this, {}, QDir(m_audioExporter->d_func()->projectDirectory()).absoluteFilePath(m_fileDirectoryEdit->text()), + filters.join(";;"), &selectedFilter); + if (path.isEmpty()) + return; + QFileInfo fileInfo(path); + m_fileNameEdit->setText(fileInfo.baseName() + (m_mixingOptionComboBox->currentIndex() == AudioExporterConfig::MO_Mixed ? "." : "_${trackIndex}_${trackName}.") + fileInfo.completeSuffix()); + m_fileDirectoryEdit->setText(fileInfo.dir().canonicalPath()); + m_fileTypeComboBox->setCurrentIndex(filters.indexOf(selectedFilter)); + } + void AudioExportDialog::showWarnings() { + QMessageBox::warning(this, {}, + AudioExporter::warningText(m_audioExporter->warning()).join("\n\n")); + } + void AudioExportDialog::showDryRunResult() { + QDialog dlg(this); + auto layout = new QVBoxLayout; + auto fileListGroupBox = new QGroupBox(tr("File List")); + auto fileListLayout = new QVBoxLayout; + auto fileListWidget = new QListWidget; + fileListWidget->setSelectionMode(QAbstractItemView::NoSelection); + auto fileList = m_audioExporter->dryRun(); + QHash fileListCountDict; + for (const auto &file : fileList) { + fileListCountDict[file]++; + } + for (const auto &file : fileList) { + auto item = new QListWidgetItem; + item->setText(file); + AudioExporter::Warning fileWarning; + if (QFileInfo::exists(file) && QFileInfo(file).isFile()) { + fileWarning |= AudioExporter::W_WillOverwrite; + } + if (fileListCountDict.value(file) > 1) { + fileWarning |= AudioExporter::W_DuplicatedFile; + } + if (fileWarning) { + item->setIcon(style()->standardIcon(QStyle::SP_MessageBoxWarning)); + item->setToolTip(AudioExporter::warningText(fileWarning).join('\n')); + } + fileListWidget->addItem(item); + } + fileListLayout->addWidget(fileListWidget); + fileListGroupBox->setLayout(fileListLayout); + layout->addWidget(fileListGroupBox); + if (m_audioExporter->warning()) { + auto warningGroupBox = new QGroupBox(tr("Warnings")); + auto warningLayout = new QVBoxLayout; + auto warningWidget = new QListWidget; + warningWidget->setWordWrap(true); + warningWidget->setSelectionMode(QAbstractItemView::NoSelection); + for (const auto &warning : AudioExporter::warningText(m_audioExporter->warning())) { + auto item = new QListWidgetItem; + item->setText(warning); + item->setIcon(style()->standardIcon(QStyle::SP_MessageBoxWarning)); + warningWidget->addItem(item); + } + warningLayout->addWidget(warningWidget); + warningGroupBox->setLayout(warningLayout); + layout->addWidget(warningGroupBox); + } + auto buttonLayout = new QHBoxLayout(); + auto okButton = new QPushButton(tr("OK")); + buttonLayout->addStretch(); + buttonLayout->addWidget(okButton); + layout->addLayout(buttonLayout); + dlg.setLayout(layout); + connect(okButton, &QAbstractButton::clicked, &dlg, &QDialog::accept); + dlg.setWindowTitle(tr("Dry Run")); + dlg.setWindowFlag(Qt::WindowContextHelpButtonHint, false); + dlg.resize(600, 400); + dlg.exec(); + } + void AudioExportDialog::updateConfig() { + if (skipUpdateFlag) + return; + AudioExporterConfig config; + config.setFileName(m_fileNameEdit->text()); + config.setFileDirectory(m_fileDirectoryEdit->text()); + config.setFileType( + static_cast(m_fileTypeComboBox->currentIndex())); + config.setFormatMono(m_formatMonoComboBox->currentIndex() == 0); + config.setFormatOption(m_formatOptionComboBox->currentIndex()); + config.setFormatQuality(m_vbrSlider->value()); + config.setFormatSampleRate(QLocale().toDouble(m_formatSampleRateComboBox->currentText())); + config.setMixingOption( + static_cast(m_mixingOptionComboBox->currentIndex())); + config.setMuteSoloEnabled(m_enableMuteSoloCheckBox->isChecked()); + config.setSourceOption( + static_cast(m_sourceComboBox->currentIndex())); + QList sourceList; + for (int i = 0; i < m_sourceListWidget->count(); i++) { + if (m_sourceListWidget->item(i)->isSelected()) + sourceList.append(i); + } + config.setSource(sourceList); + config.setTimeRange(m_rangeSelectAllRadio->isChecked() + ? AudioExporterConfig::TR_All + : AudioExporterConfig::TR_LoopSection); + m_audioExporter->setConfig(config); + if (m_audioExporter->warning()) { + m_warningButton->show(); + } else { + m_warningButton->hide(); + } + auto fileList = m_audioExporter->dryRun(); + m_fileNamePreviewLabel->setText(fileList.isEmpty() ? QString() : QFileInfo(fileList.at(0)).fileName()); + } + void AudioExportDialog::updateView() { + skipUpdateFlag = true; + auto config = m_audioExporter->config(); + m_fileNameEdit->setText(config.fileName()); + m_fileDirectoryEdit->setText(config.fileDirectory()); + m_fileTypeComboBox->setCurrentIndex(config.fileType()); + m_formatMonoComboBox->setCurrentIndex(config.formatMono() ? 0 : 1); + m_formatOptionComboBox->setCurrentIndex(config.formatOption()); + m_vbrSlider->setValue(config.formatQuality()); + QLocale locale; + locale.setNumberOptions(QLocale::OmitGroupSeparator); + m_formatSampleRateComboBox->setCurrentText(locale.toString(config.formatSampleRate())); + m_mixingOptionComboBox->setCurrentIndex(config.mixingOption()); + m_enableMuteSoloCheckBox->setChecked(config.isMuteSoloEnabled()); + m_sourceComboBox->setCurrentIndex(config.sourceOption()); + m_rangeSelectAllRadio->setChecked(config.timeRange() == AudioExporterConfig::TR_All); + skipUpdateFlag = false; + updateConfig(); + } + + void AudioExportDialog::runExport() { + auto warning = m_audioExporter->warning(); + if (warning & AudioExporter::W_LossyFormat) { + if (!askWarningBeforeExport(AudioExporter::W_LossyFormat, true)) + return; + } + if (warning & AudioExporter::W_UnrecognizedTemplate) { + if (!askWarningBeforeExport(AudioExporter::W_UnrecognizedTemplate, true)) + return; + } + if (warning & AudioExporter::W_NoFile) { + if (!askWarningBeforeExport(AudioExporter::W_NoFile)) + return; + } + if (warning & AudioExporter::W_WillOverwrite) { + if (!askWarningBeforeExport(AudioExporter::W_WillOverwrite)) + return; + } + if (warning & AudioExporter::W_DuplicatedFile) { + if (!askWarningBeforeExport(AudioExporter::W_DuplicatedFile)) + return; + } + + QDialog progressDialog(this); + auto layout = new QVBoxLayout; + + auto mainPromptLayout = new QHBoxLayout; + auto mainPromptWarningButton = new QPushButton; + mainPromptWarningButton->setVisible(false); + mainPromptWarningButton->setIcon(style()->standardIcon(QStyle::SP_MessageBoxWarning)); + mainPromptLayout->addWidget(mainPromptWarningButton, 0); + auto mainPromptLabel = new QLabel(tr("Preparing...")); + mainPromptLayout->addWidget(mainPromptLabel, 1); + layout->addLayout(mainPromptLayout); + + auto mainProgressBar = new QProgressBar; + mainProgressBar->setRange(0, 100); + mainProgressBar->setValue(0); + layout->addWidget(mainProgressBar); + + auto buttonLayout = new QHBoxLayout; + buttonLayout->addStretch(); + auto abortButton = new QPushButton(tr("Cancel")); + buttonLayout->addWidget(abortButton); + layout->addLayout(buttonLayout); + + progressDialog.setLayout(layout); + progressDialog.resize(400, progressDialog.height()); + + QHash progressRatioHash; + bool isProgressing = false; + if (m_audioExporter->config().mixingOption() == AudioExporterConfig::MO_Mixed) { + connect(m_audioExporter, &AudioExporter::progressChanged, &progressDialog, [=, &isProgressing](double ratio) { + if (!isProgressing) { + isProgressing = true; + mainPromptLabel->setText(tr("Exporting...")); + } + mainProgressBar->setValue(static_cast(ratio * 100.0)); + }); + } else { + int sourceCount = m_audioExporter->config().source().size(); + connect(m_audioExporter, &AudioExporter::progressChanged, &progressDialog, [=, &progressRatioHash, &isProgressing](double ratio, int sourceIndex) { + if (!isProgressing) { + isProgressing = true; + mainPromptLabel->setText(tr("Exporting...")); + } + progressRatioHash[sourceIndex] = ratio; + double totalRatio = 0; + for (auto value : progressRatioHash.values()) { + totalRatio += value; + } + mainProgressBar->setValue(static_cast(totalRatio / sourceCount * 100.0)); + }); + } + + QDialog warningListDialog(this); + auto warningListDialogLayout = new QVBoxLayout; + auto warningList = new QListWidget; + warningListDialogLayout->addWidget(warningList); + warningListDialog.setLayout(warningListDialogLayout); + warningListDialog.resize(300, 300); + warningListDialog.setWindowTitle(tr("Warnings")); + connect(m_audioExporter, &AudioExporter::clippingDetected, &progressDialog, [=](int sourceIndex) { + auto item = new QListWidgetItem; + if (sourceIndex == -1) { + item->setText(tr("Clipping is detected")); + } else { + item->setText(tr("Clipping is detected in track %1 \"%2\"").arg(sourceIndex + 1).arg(m_audioExporter->d_func()->trackName(sourceIndex))); + } + item->setIcon(style()->standardIcon(QStyle::SP_MessageBoxWarning)); + warningList->addItem(item); + mainPromptWarningButton->setVisible(true); + mainPromptWarningButton->setToolTip(tr("%n warning(s)", nullptr, warningList->count())); + }); + connect(m_audioExporter, &AudioExporter::warningAdded, &progressDialog, [=](const QString &message, int sourceIndex) { + Q_UNUSED(sourceIndex); // may be used in future + auto item = new QListWidgetItem; + item->setText(message); + item->setIcon(style()->standardIcon(QStyle::SP_MessageBoxWarning)); + warningList->addItem(item); + mainPromptWarningButton->setVisible(true); + mainPromptWarningButton->setToolTip(tr("%n warning(s)", nullptr, warningList->count())); + }); + + connect(mainPromptWarningButton, &QAbstractButton::clicked, &progressDialog, [=, &warningListDialog] { + warningListDialog.open(); + }); + + bool interruptFlag = true; + connect(abortButton, &QAbstractButton::clicked, &progressDialog, [=, &interruptFlag, &progressDialog] { + if (interruptFlag) { + m_audioExporter->cancel(); + } else { + progressDialog.reject(); + } + }); + + QTimer::singleShot(0, [=, &interruptFlag, &progressDialog] { + QCoreApplication::processEvents(); + auto ret = m_audioExporter->exec(); + interruptFlag = false; + abortButton->setText(tr("Close")); + if (warningList->count()) { + switch (ret) { + case AudioExporter::R_OK: + mainPromptLabel->setText(tr("Export finished with %n warning(s)", nullptr, warningList->count())); + break; + case AudioExporter::R_Abort: + mainPromptLabel->setText(tr("Export aborted with %n warning(s)", nullptr, warningList->count())); + break; + case AudioExporter::R_Fail: + mainPromptLabel->setText(tr("Export failed with %n warning(s)\n%1", nullptr, warningList->count()).arg(m_audioExporter->errorString())); + break; + } + } else { + switch (ret) { + case AudioExporter::R_OK: + progressDialog.accept(); + break; + case AudioExporter::R_Abort: + progressDialog.reject(); + break; + case AudioExporter::R_Fail: + mainPromptLabel->setText(tr("Export failed\n%1").arg(m_audioExporter->errorString())); + break; + } + } + }); + if (progressDialog.exec() == QDialog::Accepted) { + auto currentData = m_presetComboBox->currentData(); + AudioSettings::setAudioExporterCurrentPreset(currentData.isNull() ? QJsonValue(m_presetComboBox->currentIndex()) : QJsonValue(currentData.toString())); + saveTemporaryPreset(); + if (!m_keepOpenCheckBox->isChecked()) + accept(); + } + } + + bool AudioExportDialog::askWarningBeforeExport(AudioExporter::Warning warning, + bool canIgnored) { + if (AudioSettings::audioExporterIgnoredWarningFlag() & warning) + return true; + QMessageBox msgBox(this); + msgBox.setText(AudioExporter::warningText(warning)[0] + "\n\n" + tr("Continue to export?")); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + QCheckBox *checkBox = nullptr; + if (canIgnored) { + checkBox = new QCheckBox(tr("Don't ask again")); + msgBox.setCheckBox(checkBox); + } + if (msgBox.exec() == QMessageBox::Yes) { + if (canIgnored && checkBox->isChecked()) + AudioSettings::setAudioExporterIgnoredWarningFlag( + AudioSettings::audioExporterIgnoredWarningFlag() | warning); + return true; + } else { + return false; + } + } + + void AudioExportDialog::saveTemporaryPreset() { + ProjectAddOn::get(m_audioExporter->windowHandle())->setData("audioExporter.temporaryPreset", m_audioExporter->config().toVariantMap()); + } + + void AudioExportDialog::restoreTemporaryPreset() { + m_audioExporter->setConfig(AudioExporterConfig::fromVariantMap(ProjectAddOn::get(m_audioExporter->windowHandle())->data("audioExporter.temporaryPreset").toMap())); + } + + bool AudioExportDialog::hasTemporaryPreset() const { + return ProjectAddOn::get(m_audioExporter->windowHandle())->hasData("audioExporter.temporaryPreset"); + } + + +} diff --git a/src/plugins/audioplugin/internal/dialogs/audioexportdialog.h b/src/plugins/audioplugin/internal/dialogs/audioexportdialog.h index 2650ae2..0799a7a 100644 --- a/src/plugins/audioplugin/internal/dialogs/audioexportdialog.h +++ b/src/plugins/audioplugin/internal/dialogs/audioexportdialog.h @@ -3,6 +3,13 @@ #include +#include + +namespace Core { + class IProjectWindow; +} + +class QLabel; class QLineEdit; class QTextEdit; class QComboBox; @@ -18,7 +25,8 @@ namespace Audio::Internal { class AudioExportDialog : public QDialog { Q_OBJECT public: - explicit AudioExportDialog(QWidget *parent = nullptr); + explicit AudioExportDialog(QWidget *parent = nullptr) : AudioExportDialog(nullptr, parent) {} + explicit AudioExportDialog(Core::IProjectWindow *windowHandle, QWidget *parent = nullptr); ~AudioExportDialog() override; private: @@ -26,6 +34,7 @@ namespace Audio::Internal { QPushButton *m_presetDeleteButton; QLineEdit *m_fileDirectoryEdit; QLineEdit *m_fileNameEdit; + QLabel *m_fileNamePreviewLabel; QComboBox *m_fileTypeComboBox; QComboBox *m_formatMonoComboBox; QComboBox *m_formatOptionComboBox; @@ -42,6 +51,26 @@ namespace Audio::Internal { QPushButton *m_warningButton; QString m_warningText; + + AudioExporter *m_audioExporter; + + QStringList projectTrackList() const; + + void browseFile(); + void showWarnings(); + void showDryRunResult(); + void updateConfig(); + void updateView(); + + bool skipUpdateFlag = false; + + void runExport(); + + bool askWarningBeforeExport(AudioExporter::Warning warning, bool canIgnored = false); + + void saveTemporaryPreset(); + void restoreTemporaryPreset(); + bool hasTemporaryPreset() const; }; } diff --git a/src/plugins/audioplugin/internal/settings/audioexportpage.cpp b/src/plugins/audioplugin/internal/settings/audioexportpage.cpp index bcecf38..458f8b5 100644 --- a/src/plugins/audioplugin/internal/settings/audioexportpage.cpp +++ b/src/plugins/audioplugin/internal/settings/audioexportpage.cpp @@ -4,8 +4,9 @@ #include #include #include +#include -#include +#include namespace Audio::Internal { @@ -16,20 +17,32 @@ namespace Audio::Internal { auto mainLayout = new QFormLayout; auto enableClippingCheckCheckBox = new QCheckBox(tr("Enable &clipping check")); mainLayout->addRow(enableClippingCheckCheckBox); - auto threadCountSpinBox = new SVS::ExpressionSpinBox; - threadCountSpinBox->setRange(0, QThread::idealThreadCount()); - threadCountSpinBox->setSpecialValueText(tr("Auto")); - mainLayout->addRow(tr("Number of &threads for exporting"), threadCountSpinBox); - auto multiThreadLabel = new QLabel(tr("Audio exporting will be multi-threaded when the mixing option is \"separated\"")); - multiThreadLabel->setWordWrap(true); - multiThreadLabel->setAlignment(Qt::AlignTop); - mainLayout->addWidget(multiThreadLabel); + auto resetWarningDialogsLayout = new QHBoxLayout; + auto resetWarningDialogsButton = new QPushButton(tr("Reset &Warning Dialogs")); + resetWarningDialogsLayout->addWidget(resetWarningDialogsButton); + auto resetLabel = new QLabel; + resetWarningDialogsLayout->addWidget(resetLabel); + resetWarningDialogsLayout->addStretch(); + mainLayout->addRow(resetWarningDialogsLayout); setLayout(mainLayout); + + enableClippingCheckCheckBox->setChecked(m_clippingCheckEnabled = AudioSettings::audioExporterClippingCheckEnabled()); + connect(enableClippingCheckCheckBox, &QAbstractButton::clicked, this, [=](bool checked) { + m_clippingCheckEnabled = checked; + }); + connect(resetWarningDialogsButton, &QAbstractButton::clicked, this, [=] { + AudioSettings::setAudioExporterIgnoredWarningFlag(0); + resetWarningDialogsButton->setDisabled(true); + resetLabel->setText(tr("Warning dialogs have been reset")); + }); } void accept() { - + AudioSettings::setAudioExporterClippingCheckEnabled(m_clippingCheckEnabled); } + + private: + bool m_clippingCheckEnabled; }; AudioExportPage::AudioExportPage(QObject *parent) : Core::ISettingPage("audio.AudioExport", parent) { diff --git a/src/plugins/audioplugin/internal/utils/audiosettings.cpp b/src/plugins/audioplugin/internal/utils/audiosettings.cpp index 06a95d3..3bcad98 100644 --- a/src/plugins/audioplugin/internal/utils/audiosettings.cpp +++ b/src/plugins/audioplugin/internal/utils/audiosettings.cpp @@ -117,6 +117,8 @@ namespace Audio::Internal { AUDIO_AUDIO_SETTINGS_OPTION_IMPLEMENTATION_QJSONVALUE(vstTheme, setVstTheme) AUDIO_AUDIO_SETTINGS_OPTION_IMPLEMENTATION_QJSONVALUE(audioExporterPresets, setAudioExporterPresets) - AUDIO_AUDIO_SETTINGS_OPTION_IMPLEMENTATION_1(audioExporterClippingCheckEnabled, setAudioExporterClippingCheckEnabled) + AUDIO_AUDIO_SETTINGS_OPTION_IMPLEMENTATION_2(audioExporterClippingCheckEnabled, setAudioExporterClippingCheckEnabled, true) + AUDIO_AUDIO_SETTINGS_OPTION_IMPLEMENTATION_QJSONVALUE(audioExporterCurrentPreset, setAudioExporterCurrentPreset) + AUDIO_AUDIO_SETTINGS_OPTION_IMPLEMENTATION_1(audioExporterIgnoredWarningFlag, setAudioExporterIgnoredWarningFlag) } // Audio \ No newline at end of file diff --git a/src/plugins/audioplugin/internal/utils/audiosettings.h b/src/plugins/audioplugin/internal/utils/audiosettings.h index ecc4c09..990c7ac 100644 --- a/src/plugins/audioplugin/internal/utils/audiosettings.h +++ b/src/plugins/audioplugin/internal/utils/audiosettings.h @@ -51,6 +51,8 @@ namespace Audio::Internal { AUDIO_AUDIO_SETTINGS_OPTION_DECLARATION(audioExporterPresets, setAudioExporterPresets, QJsonValue) AUDIO_AUDIO_SETTINGS_OPTION_DECLARATION(audioExporterClippingCheckEnabled, setAudioExporterClippingCheckEnabled, bool) + AUDIO_AUDIO_SETTINGS_OPTION_DECLARATION(audioExporterCurrentPreset, setAudioExporterCurrentPreset, QJsonValue) + AUDIO_AUDIO_SETTINGS_OPTION_DECLARATION(audioExporterIgnoredWarningFlag, setAudioExporterIgnoredWarningFlag, int) };