Added: VST Plugin support. Add and configure plugins via Configuration Editor. The plugin's architecture has to match the OS architecture, so most people will need 64-bit plugins. The subdirectory plugins is offered to put plugins into, but they can be opened from any directory with sufficient permissions.

Fixed: When trying to add a high-pass filter in the Configuration Editor, it was instead configured to be a low-pass filter.
This commit is contained in:
jthedering committed 2017-06-17 13:04:35 +00:00
1 parent 989812ba36
commit a24eaa0cd9
58 files changed
+3334 -151

No files matched your search

+1 -1
View File
@@ -32,7 +32,7 @@ QList<FilterTemplate> BiQuadFilterGUIFactory::createFilterTemplates()
QList<FilterTemplate> list;
list.append(FilterTemplate(tr("Peaking filter"), "Filter: ON PK Fc 100 Hz Gain 0 dB Q 10", path));
list.append(FilterTemplate(tr("Low-pass filter"), "Filter: ON LP Fc 100 Hz", path));
list.append(FilterTemplate(tr("High-pass filter"), "Filter: ON LP Fc 100 Hz", path));
list.append(FilterTemplate(tr("High-pass filter"), "Filter: ON HP Fc 100 Hz", path));
list.append(FilterTemplate(tr("Band-pass filter"), "Filter: ON BP Fc 100 Hz Q 10", path));
list.append(FilterTemplate(tr("Low-shelf filter"), "Filter: ON LS Fc 100 Hz Gain 0 dB", path));
list.append(FilterTemplate(tr("High-shelf filter"), "Filter: ON HS Fc 100 Hz Gain 0 dB", path));
+10 -3
View File
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>652</width>
<height>65</height>
<width>665</width>
<height>79</height>
</rect>
</property>
<property name="windowTitle">
@@ -58,7 +58,14 @@
</widget>
</item>
<item row="0" column="1">
<widget class="ResizingLineEdit" name="pathLineEdit"/>
<widget class="ResizingLineEdit" name="pathLineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QGroupBox" name="groupBox">
+10 -1
View File
@@ -175,8 +175,9 @@ void CopyFilterGUIConnectionItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent
if (isDecibel)
text += " dB";
ResizingLineEdit* lineEdit = new ResizingLineEdit("");
ResizingLineEdit* lineEdit = new ResizingLineEdit(text, true);
connect(lineEdit, SIGNAL(editingFinished()), this, SLOT(lineEditEditingFinished()));
connect(lineEdit, SIGNAL(editingCanceled()), this, SLOT(lineEditEditingCanceled()));
QGraphicsProxyWidget* proxyItem = scene()->addWidget(lineEdit);
QLineF l = line();
QPointF center = (l.p1() + l.p2()) / 2;
@@ -233,6 +234,14 @@ void CopyFilterGUIConnectionItem::lineEditEditingFinished()
emit((CopyFilterGUIScene*)scene())->updateModel();
}
void CopyFilterGUIConnectionItem::lineEditEditingCanceled()
{
QLineEdit* lineEdit = qobject_cast<QLineEdit*>(QObject::sender());
lineEdit->setVisible(false);
lineEdit->deleteLater();
}
CopyFilterGUIChannelItem* CopyFilterGUIConnectionItem::getSource() const
{
return source;
@@ -55,6 +55,7 @@ protected:
private slots:
void lineEditEditingFinished();
void lineEditEditingCanceled();
private:
CopyFilterGUIChannelItem* source = NULL;
+19 -6
View File
@@ -162,8 +162,9 @@ std::vector<Assignment> CopyFilterGUIScene::buildAssignments()
void CopyFilterGUIScene::addOutputChannel()
{
ResizingLineEdit* lineEdit = new ResizingLineEdit("");
ResizingLineEdit* lineEdit = new ResizingLineEdit("", true);
connect(lineEdit, SIGNAL(editingFinished()), this, SLOT(lineEditEditingFinished()));
connect(lineEdit, SIGNAL(editingCanceled()), this, SLOT(lineEditEditingCanceled()));
QGraphicsProxyWidget* proxyItem = addWidget(lineEdit);
QPointF point = getNextChannelPoint(lastOutputItem, true);
QRectF rect;
@@ -183,13 +184,25 @@ void CopyFilterGUIScene::lineEditEditingFinished()
return;
QString text = lineEdit->text();
if (text != "")
{
CopyFilterGUIChannelItem* item = new CopyFilterGUIChannelItem(text, true);
item->setPos(getNextChannelPoint(lastOutputItem, true));
addItem(item);
lastOutputItem = item;
CopyFilterGUIChannelItem* item = new CopyFilterGUIChannelItem(text, true);
item->setPos(getNextChannelPoint(lastOutputItem, true));
addItem(item);
lastOutputItem = item;
addProxyItem->setPos(getNextChannelPoint(lastOutputItem, true));
}
addProxyItem->setVisible(true);
lineEdit->setVisible(false);
lineEdit->deleteLater();
}
void CopyFilterGUIScene::lineEditEditingCanceled()
{
QLineEdit* lineEdit = qobject_cast<QLineEdit*>(QObject::sender());
addProxyItem->setPos(getNextChannelPoint(lastOutputItem, true));
addProxyItem->setVisible(true);
lineEdit->setVisible(false);
+1
View File
@@ -43,6 +43,7 @@ protected:
private slots:
void addOutputChannel();
void lineEditEditingFinished();
void lineEditEditingCanceled();
private:
QGraphicsItem* lastOutputItem;
+8 -1
View File
@@ -51,7 +51,14 @@
</widget>
</item>
<item row="0" column="1">
<widget class="ResizingLineEdit" name="pathLineEdit"/>
<widget class="ResizingLineEdit" name="pathLineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="selectFileToolButton">
+480
View File
@@ -0,0 +1,480 @@
/*
This file is part of Equalizer APO, a system-wide equalizer.
Copyright (C) 2017 Jonas Thedering
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <QFileInfo>
#include <QFileDialog>
#include <QSettings>
#include <QAbstractEventDispatcher>
#include <QStringList>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "helpers/aeffectx.h"
#include "helpers/StringHelper.h"
#include "Editor/helpers/DPIHelper.h"
#include "Editor/MainWindow.h"
#include "VSTPluginFilterGUIDialog.h"
#include "VSTPluginFilterGUI.h"
#include "ui_VSTPluginFilterGUI.h"
using namespace std;
using namespace std::placeholders;
VSTPluginFilterGUI::VSTPluginFilterGUI(std::shared_ptr<VSTPluginLibrary> library, const std::wstring& chunkData, const std::unordered_map<std::wstring, float>& paramMap)
: ui(new Ui::VSTPluginFilterGUI), library(library), chunkData(chunkData), paramMap(paramMap)
{
ui->setupUi(this);
ui->frame->setVisible(false);
updatePermissionWarning();
QString absolutePath = QString::fromStdWString(library->getLibPath());
QDir pluginsDir(QString::fromStdWString(VSTPluginLibrary::getDefaultPluginPath()));
QString relativePath = QDir::toNativeSeparators(pluginsDir.relativeFilePath(absolutePath));
if (relativePath.startsWith(QDir::toNativeSeparators("../../")))
relativePath = absolutePath;
ui->pathLineEdit->setText(relativePath);
QMenu* menu = new QMenu(ui->optionsButton);
menu->addAction(ui->embedAction);
ui->optionsButton->setMenu(menu);
}
VSTPluginFilterGUI::~VSTPluginFilterGUI()
{
if (effect != NULL)
{
if (ui->embedAction->isChecked())
on_embedAction_toggled(false);
delete effect;
effect = NULL;
}
delete ui;
}
void VSTPluginFilterGUI::store(QString& command, QString& parameters)
{
command = "VSTPlugin";
QString absolutePath = QString::fromStdWString(library->getLibPath());
QDir pluginsDir(QString::fromStdWString(VSTPluginLibrary::getDefaultPluginPath()));
QString relativePath = QDir::toNativeSeparators(pluginsDir.relativeFilePath(absolutePath));
if (relativePath.startsWith(QDir::toNativeSeparators("../../")))
relativePath = absolutePath;
if (relativePath.contains(" "))
relativePath = "\"" + relativePath + "\"";
parameters = "Library " + relativePath;
if (chunkData != L"")
{
parameters += " ChunkData \"" + QString::fromStdWString(chunkData) + "\"";
}
else
{
for (auto it : paramMap)
{
QString name = QString::fromStdWString(it.first);
if (name.contains(" ") || name.contains("\""))
name = "\"" + name.replace("\"", "\"\"") + "\"";
parameters += " " + name + " " + QString("%1").arg(it.second);
}
}
}
void VSTPluginFilterGUI::loadPreferences(const QVariantMap& prefs)
{
autoApplyDialog = prefs.value("autoApplyDialog").toBool();
if (prefs.value("embed").toBool())
// will also call initPlugin
ui->embedAction->setChecked(true);
else
initPlugin();
}
void VSTPluginFilterGUI::storePreferences(QVariantMap& prefs)
{
prefs.insert("embed", ui->embedAction->isChecked());
prefs.insert("autoApplyDialog", autoApplyDialog);
}
void VSTPluginFilterGUI::on_openPanelButton_clicked()
{
initPlugin();
if (effect != NULL)
{
effect->writeToEffect(chunkData, paramMap);
VSTPluginFilterGUIDialog dialog(this, effect, autoApplyDialog);
connect(dialog.getApplyButton(), SIGNAL(pressed()), SLOT(applyDialog()));
connect(dialog.getAutoApplyCheckBox(), SIGNAL(toggled(bool)), SLOT(autoApplyToggled(bool)));
connect(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()), SLOT(on_idle()));
if (dialog.exec() == QDialog::Accepted)
{
effect->readFromEffect(chunkData, paramMap);
updateModel();
updatePermissionWarning();
}
disconnect(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()), this, SLOT(on_idle()));
}
}
void VSTPluginFilterGUI::applyDialog()
{
effect->readFromEffect(chunkData, paramMap);
updateModel();
updatePermissionWarning();
}
void VSTPluginFilterGUI::autoApplyToggled(bool checked)
{
autoApplyDialog = checked;
}
void VSTPluginFilterGUI::initPlugin()
{
if (effect != NULL)
return;
QColor color;
QString text;
if (library->getLibPath() == L"")
{
text = tr("No file selected.");
color = Qt::red;
}
else
{
int result = library->initialize();
if (result < 0)
{
color = Qt::red;
switch (result)
{
case AbstractLibrary::FILE_NOT_FOUND:
text = tr("File not found.");
break;
case AbstractLibrary::LOADING_FAILED:
text = tr("Library could not be loaded.");
break;
case AbstractLibrary::FUNCTIONS_MISSING:
text = tr("Library does not contain needed functions.");
break;
case AbstractLibrary::WRONG_ARCHITECTURE:
#ifdef _WIN64
int bitDepth = 64;
#else
int bitDepth = 32;
#endif
text = tr("Library has the wrong architecture. Only %1-bit libraries are supported.").arg(bitDepth);
break;
}
}
else
{
effect = new VSTPluginInstance(library, 1);
if (effect->initialize())
{
effect->setLanguage(QLocale().language() == QLocale::German ? 2 : 1);
effect->setAutomateFunc(bind(&VSTPluginFilterGUI::onAutomate, this));
color = Qt::black;
text = QString::fromStdWString(effect->getName());
}
else
{
delete effect;
effect = NULL;
color = Qt::red;
text = tr("Plugin crashed during initialization.");
}
}
}
QPalette palette = ui->statusLabel->palette();
palette.setColor(QPalette::Active, QPalette::WindowText, color);
palette.setColor(QPalette::Inactive, QPalette::WindowText, color);
ui->statusLabel->setPalette(palette);
ui->statusLabel->setText(text);
}
void VSTPluginFilterGUI::on_pathLineEdit_editingFinished()
{
if (QString::fromStdWString(library->getLibPath()) != ui->pathLineEdit->text())
{
int oldId = 0;
if (effect != NULL)
{
oldId = effect->uniqueID();
if (ui->embedAction->isChecked())
on_embedAction_toggled(false);
delete effect;
effect = NULL;
}
QDir pluginsDir(QString::fromStdWString(VSTPluginLibrary::getDefaultPluginPath()));
QString path = ui->pathLineEdit->text();
if (path.length() > 0)
path = QDir::toNativeSeparators(QFileInfo(pluginsDir, ui->pathLineEdit->text()).absoluteFilePath());
library = VSTPluginLibrary::getInstance(path.toStdWString());
initPlugin();
if (effect == NULL || oldId == 0 || effect->uniqueID() != oldId)
{
chunkData = L"";
paramMap.clear();
}
updateModel();
updatePermissionWarning();
if (ui->embedAction->isChecked())
on_embedAction_toggled(true);
}
}
void VSTPluginFilterGUI::on_selectButton_clicked()
{
QDir pluginsDir(QString::fromStdWString(VSTPluginLibrary::getDefaultPluginPath()));
QSettings settings(QString::fromWCharArray(EDITOR_REGPATH), QSettings::NativeFormat);
QString lastDir = settings.value("vst/lastDir", "").toString();
if (lastDir == "")
lastDir = pluginsDir.absolutePath();
QFileInfo fileInfo(lastDir);
QString path = ui->pathLineEdit->text();
if (path.length() > 0)
fileInfo.setFile(pluginsDir, path);
QFileDialog dialog(this, tr("Select VST plugin"), fileInfo.absoluteFilePath(), "*.dll");
dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilter(tr("VST plugins (*.dll)"));
if (path.length() > 0)
dialog.selectFile(fileInfo.fileName());
if (dialog.exec() == QDialog::Accepted)
{
QString absolutePath = dialog.selectedFiles().first();
settings.setValue("vst/lastDir", QDir::toNativeSeparators(QFileInfo(absolutePath).absolutePath()));
QString relativePath = pluginsDir.relativeFilePath(absolutePath);
if (relativePath.startsWith("../../"))
relativePath = absolutePath;
ui->pathLineEdit->setText(QDir::toNativeSeparators(relativePath));
on_pathLineEdit_editingFinished();
}
}
void VSTPluginFilterGUI::on_embedAction_toggled(bool checked)
{
initPlugin();
ui->openPanelButton->setVisible(!checked);
bool enable = checked;
if (effect == NULL)
enable = false;
bool wasEnabled = ui->frame->isVisible();
if (enable != wasEnabled)
{
ui->frame->setVisible(enable);
ui->statusLabel->setVisible(!enable);
if (enable)
{
if (embedPlugin())
{
effect->setSizeWindowFunc(bind(&VSTPluginFilterGUI::onSizeWindow, this, _1, _2));
connect(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()), SLOT(on_idle()));
}
else
{
ui->frame->setVisible(false);
ui->statusLabel->setVisible(true);
QPalette palette = ui->statusLabel->palette();
palette.setColor(QPalette::Active, QPalette::WindowText, Qt::red);
palette.setColor(QPalette::Inactive, QPalette::WindowText, Qt::red);
ui->statusLabel->setPalette(palette);
ui->statusLabel->setText(tr("Plugin crashed when opening panel."));
}
}
else
{
if (effect != NULL)
{
effect->stopEditing();
effect->setSizeWindowFunc(nullptr);
}
disconnect(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()), this, SLOT(on_idle()));
}
}
}
void VSTPluginFilterGUI::on_idle()
{
if (effect != NULL)
{
effect->doIdle();
if (ui->frame->isVisible() || autoApplyDialog)
{
if (!lastReadTimer.isValid() || lastReadTimer.elapsed() > 1000)
{
wstring newChunkData;
unordered_map<std::wstring, float> newParamMap;
effect->readFromEffect(newChunkData, newParamMap);
if (newChunkData != chunkData || newParamMap != paramMap)
{
chunkData = newChunkData;
paramMap = newParamMap;
updateModel();
updatePermissionWarning();
}
lastReadTimer.restart();
}
}
}
}
void VSTPluginFilterGUI::onAutomate()
{
if (ui->frame->isVisible() || autoApplyDialog)
{
effect->readFromEffect(chunkData, paramMap);
updateModel();
updatePermissionWarning();
}
}
void VSTPluginFilterGUI::onSizeWindow(int w, int h)
{
if (ui->frame->isVisible())
ui->frame->setFixedSize(w, h);
}
bool VSTPluginFilterGUI::embedPlugin()
{
bool result = true;
__try
{
effect->writeToEffect(chunkData, paramMap);
HWND hwnd = (HWND)ui->frame->winId();
short width, height;
effect->startEditing(hwnd, &width, &height);
ui->frame->setFixedSize(width, height);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
result = false;
}
return result;
}
void VSTPluginFilterGUI::updatePermissionWarning()
{
if (effect == NULL)
{
ui->warningTextEdit->setVisible(false);
return;
}
ACCESS_MASK mask = GENERIC_READ;
try
{
mask = RegistryHelper::getFileAccessForUser(library->getLibPath(), SECURITY_LOCAL_SERVICE_RID);
}
catch (RegistryException e)
{
// ignore
}
if ((mask & GENERIC_READ) != GENERIC_READ && (mask & FILE_GENERIC_READ) != FILE_GENERIC_READ)
{
QString text = tr("The library is not readable by the audio service.\nChange the file permissions or copy the file to the plugins directory.");
ui->warningTextEdit->setPlainText(text);
QSize textSize = ui->warningTextEdit->fontMetrics().size(0, text);
ui->warningTextEdit->setFixedSize(textSize + DPIHelper::scale(QSize(40, 15)));
ui->warningTextEdit->setVisible(true);
return;
}
QStringList files;
if (chunkData != L"" && chunkData.length() < 100000)
{
QByteArray bytes = QByteArray::fromBase64(QString::fromStdWString(chunkData).toUtf8());
QString string = QString::fromUtf8(bytes.data(), bytes.length());
QRegExp regexp("[A-Za-z]:(?:\\\\[\\w \\(\\)-]+)+\\.[A-Za-z]{3}");
int offset = 0;
while (offset >= 0)
{
offset = regexp.indexIn(string, offset);
if (offset >= 0)
{
QString path = regexp.cap();
QFile file(path);
if (file.exists())
{
ACCESS_MASK mask = GENERIC_READ;
try
{
mask = RegistryHelper::getFileAccessForUser(path.toStdWString(), SECURITY_LOCAL_SERVICE_RID);
}
catch (RegistryException e)
{
// ignore
}
if ((mask & GENERIC_READ) != GENERIC_READ && (mask & FILE_GENERIC_READ) != FILE_GENERIC_READ)
files.append(path);
}
offset += regexp.matchedLength();
}
}
}
if (files.isEmpty())
{
ui->warningTextEdit->setVisible(false);
ui->warningTextEdit->setPlainText("");
}
else
{
files.removeDuplicates();
QString text = tr("The plugin seemingly accesses these files not readable by the audio service:\n"
"%0\n"
"Change the file permissions or copy the files to the config directory.").arg(files.join("\n"));
ui->warningTextEdit->setPlainText(text);
QSize textSize = ui->warningTextEdit->fontMetrics().size(0, text);
ui->warningTextEdit->setFixedSize(textSize + DPIHelper::scale(QSize(40, 15)));
ui->warningTextEdit->setVisible(true);
}
}
+66
View File
@@ -0,0 +1,66 @@
/*
This file is part of Equalizer APO, a system-wide equalizer.
Copyright (C) 2017 Jonas Thedering
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <memory>
#include <QElapsedTimer>
#include "Editor/IFilterGUI.h"
#include "helpers/VSTPluginLibrary.h"
namespace Ui {
class VSTPluginFilterGUI;
}
class VSTPluginFilterGUI : public IFilterGUI
{
Q_OBJECT
public:
explicit VSTPluginFilterGUI(std::shared_ptr<VSTPluginLibrary> library, const std::wstring& chunkData, const std::unordered_map<std::wstring, float>& paramMap);
~VSTPluginFilterGUI();
void store(QString& command, QString& parameters) override;
void loadPreferences(const QVariantMap& prefs) override;
void storePreferences(QVariantMap& prefs) override;
void onAutomate();
void onSizeWindow(int w, int h);
private slots:
void on_openPanelButton_clicked();
void applyDialog();
void autoApplyToggled(bool checked);
void on_pathLineEdit_editingFinished();
void on_selectButton_clicked();
void on_embedAction_toggled(bool checked);
void on_idle();
private:
void initPlugin();
bool embedPlugin();
void updatePermissionWarning();
Ui::VSTPluginFilterGUI* ui;
std::shared_ptr<VSTPluginLibrary> library;
VSTPluginInstance* effect = NULL;
std::wstring chunkData;
std::unordered_map<std::wstring, float> paramMap;
bool autoApplyDialog = false;
QElapsedTimer lastReadTimer;
};
+203
View File
@@ -0,0 +1,203 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>VSTPluginFilterGUI</class>
<widget class="QWidget" name="VSTPluginFilterGUI">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>542</width>
<height>166</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QGridLayout" name="gridLayout_3" columnstretch="0,0,0,0,1">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="verticalSpacing">
<number>5</number>
</property>
<item row="0" column="1">
<widget class="ResizingLineEdit" name="pathLineEdit"/>
</item>
<item row="1" column="2" colspan="2">
<widget class="QPushButton" name="openPanelButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Open panel</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>VST plugin:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="statusLabel">
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
<item row="0" column="4">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="3">
<widget class="QToolButton" name="optionsButton">
<property name="text">
<string>Options</string>
</property>
<property name="popupMode">
<enum>QToolButton::MenuButtonPopup</enum>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextOnly</enum>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="selectButton">
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="../Editor.qrc">
<normaloff>:/icons/document-open.ico</normaloff>:/icons/document-open.ico</iconset>
</property>
</widget>
</item>
<item row="2" column="0" colspan="4">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
<item row="3" column="0" colspan="4">
<widget class="QPlainTextEdit" name="warningTextEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>127</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>127</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>240</red>
<green>240</green>
<blue>240</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
</widget>
</item>
</layout>
<action name="embedAction">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Embed</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>ResizingLineEdit</class>
<extends>QLineEdit</extends>
<header>Editor/widgets/ResizingLineEdit.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../Editor.qrc"/>
</resources>
<connections>
<connection>
<sender>optionsButton</sender>
<signal>clicked()</signal>
<receiver>optionsButton</receiver>
<slot>showMenu()</slot>
<hints>
<hint type="sourcelabel">
<x>288</x>
<y>12</y>
</hint>
<hint type="destinationlabel">
<x>288</x>
<y>12</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+75
View File
@@ -0,0 +1,75 @@
/*
This file is part of Equalizer APO, a system-wide equalizer.
Copyright (C) 2017 Jonas Thedering
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <QPushButton>
#include "VSTPluginFilterGUIDialog.h"
#include "ui_VSTPluginFilterGUIDialog.h"
using namespace std;
using namespace std::placeholders;
VSTPluginFilterGUIDialog::VSTPluginFilterGUIDialog(QWidget* parent, VSTPluginInstance* effect, bool autoApply)
: QDialog(parent, Qt::WindowCloseButtonHint),
ui(new Ui::VSTPluginFilterGUIDialog),
effect(effect)
{
ui->setupUi(this);
ui->autoApplyCheckBox->setChecked(autoApply);
QString name = QString::fromStdWString(effect->getName());
setWindowTitle(name);
HWND hwnd = (HWND)ui->frame->winId();
short width, height;
effect->startEditing(hwnd, &width, &height);
ui->frame->setFixedSize(width, height);
effect->setSizeWindowFunc(bind(&VSTPluginFilterGUIDialog::onSizeWindow, this, _1, _2));
}
VSTPluginFilterGUIDialog::~VSTPluginFilterGUIDialog()
{
effect->stopEditing();
effect->setSizeWindowFunc(nullptr);
delete ui;
}
QPushButton* VSTPluginFilterGUIDialog::getApplyButton()
{
return ui->buttonBox->button(QDialogButtonBox::Apply);
}
QCheckBox* VSTPluginFilterGUIDialog::getAutoApplyCheckBox()
{
return ui->autoApplyCheckBox;
}
void VSTPluginFilterGUIDialog::onSizeWindow(int w, int h)
{
ui->frame->setFixedSize(w, h);
}
void VSTPluginFilterGUIDialog::on_autoApplyCheckBox_clicked(bool checked)
{
if (checked)
getApplyButton()->click();
}
+49
View File
@@ -0,0 +1,49 @@
/*
This file is part of Equalizer APO, a system-wide equalizer.
Copyright (C) 2017 Jonas Thedering
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <QDialog>
#include <QCheckBox>
#include "helpers/VSTPluginInstance.h"
namespace Ui {
class VSTPluginFilterGUIDialog;
}
class VSTPluginFilterGUIDialog : public QDialog
{
Q_OBJECT
public:
explicit VSTPluginFilterGUIDialog(QWidget* parent, VSTPluginInstance* effect, bool autoApply);
~VSTPluginFilterGUIDialog();
QPushButton* getApplyButton();
QCheckBox* getAutoApplyCheckBox();
void onSizeWindow(int w, int h);
private slots:
void on_autoApplyCheckBox_clicked(bool checked);
private:
Ui::VSTPluginFilterGUIDialog* ui;
VSTPluginInstance* effect;
};
+87
View File
@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>VSTPluginFilterGUIDialog</class>
<widget class="QDialog" name="VSTPluginFilterGUIDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>459</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QCheckBox" name="autoApplyCheckBox">
<property name="text">
<string>Apply automatically</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>VSTPluginFilterGUIDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>VSTPluginFilterGUIDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+62
View File
@@ -0,0 +1,62 @@
/*
This file is part of Equalizer APO, a system-wide equalizer.
Copyright (C) 2017 Jonas Thedering
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "helpers/VSTPluginLibrary.h"
#include "helpers/StringHelper.h"
#include "filters/VSTPluginFilterFactory.h"
#include "filters/VSTPluginFilter.h"
#include "VSTPluginFilterGUI.h"
#include "VSTPluginFilterGUIFactory.h"
using namespace std;
QList<FilterTemplate> VSTPluginFilterGUIFactory::createFilterTemplates()
{
QList<FilterTemplate> list;
list.append(FilterTemplate(tr("VST plugin"), "VSTPlugin:", QStringList(tr("Plugins"))));
return list;
}
IFilterGUI* VSTPluginFilterGUIFactory::createFilterGUI(QString& command, QString& parameters)
{
VSTPluginFilterGUI* result = NULL;
if (command == "VSTPlugin")
{
VSTPluginFilterFactory factory;
std::vector<IFilter*> filters = factory.createFilter(L"", command.toStdWString(), parameters.toStdWString());
if (!filters.empty())
{
VSTPluginFilter* filter = (VSTPluginFilter*)filters[0];
result = new VSTPluginFilterGUI(filter->getLibrary(), filter->getChunkData(), filter->getParamMap());
}
else
{
result = new VSTPluginFilterGUI(VSTPluginLibrary::getInstance(L""), L"", unordered_map<wstring, float>());
}
for (IFilter* f : filters)
{
f->~IFilter();
MemoryHelper::free(f);
}
}
return result;
}
+30
View File
@@ -0,0 +1,30 @@
/*
This file is part of Equalizer APO, a system-wide equalizer.
Copyright (C) 2017 Jonas Thedering
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include "Editor/IFilterGUIFactory.h"
class VSTPluginFilterGUIFactory : public IFilterGUIFactory
{
Q_OBJECT
public:
QList<FilterTemplate> createFilterTemplates() override;
IFilterGUI* createFilterGUI(QString& command, QString& parameters) override;
};