Added: Analysis panel which shows the calculated frequency response of the filters for the selected device and channel.
Improved: GUIs of GraphicEQ and Copy command can now be resized Improved: GraphicEQ GUI can now be zoomed separately in X and Y direction using mouse wheel on rulers. Also now shows values at mouse position. Fixed: Original APO was not released when E-APO was shutting down, leading to a memory leak.
This commit is contained in:
1 parent
04d22adb07
commit
0895d84055
49 files changed
+2228
-267
No files matched your search
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
This file is part of EqualizerAPO, a system-wide equalizer.
|
||||
Copyright (C) 2015 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 <cmath>
|
||||
#include "AnalysisPlotScene.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
AnalysisPlotScene::AnalysisPlotScene(QObject* parent)
|
||||
: FrequencyPlotScene(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void AnalysisPlotScene::setFreqData(fftwf_complex* freqData, int frameCount, unsigned sampleRate)
|
||||
{
|
||||
nodes.clear();
|
||||
for(int i = 0; i < frameCount / 2; i++)
|
||||
{
|
||||
float freq = (i * 1.0f / frameCount) * sampleRate;
|
||||
// GainIterator can't handle 0 Hz node
|
||||
if(freq == 0.0f)
|
||||
freq = 0.001f;
|
||||
float gain = sqrt(freqData[i][0] * freqData[i][0] + freqData[i][1] * freqData[i][1]);
|
||||
float dbGain = log10(gain) * 20;
|
||||
nodes.push_back(FilterNode(freq, dbGain));
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
vector<FilterNode> AnalysisPlotScene::getNodes() const
|
||||
{
|
||||
return nodes;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
This file is part of EqualizerAPO, a system-wide equalizer.
|
||||
Copyright (C) 2015 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 <vector>
|
||||
#include <fftw3.h>
|
||||
|
||||
#include "Editor/widgets/FrequencyPlotScene.h"
|
||||
#include "helpers/GainIterator.h"
|
||||
|
||||
class AnalysisPlotScene : public FrequencyPlotScene
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AnalysisPlotScene(QObject* parent = 0);
|
||||
|
||||
void setFreqData(fftwf_complex* freqData, int frameCount, unsigned sampleRate);
|
||||
|
||||
std::vector<FilterNode> getNodes() const;
|
||||
|
||||
private:
|
||||
std::vector<FilterNode> nodes;
|
||||
};
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
This file is part of EqualizerAPO, a system-wide equalizer.
|
||||
Copyright (C) 2015 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 <algorithm>
|
||||
|
||||
#include "helpers/GainIterator.h"
|
||||
#include "AnalysisPlotScene.h"
|
||||
#include "AnalysisPlotView.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
AnalysisPlotView::AnalysisPlotView(QWidget* parent)
|
||||
: FrequencyPlotView(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void AnalysisPlotView::drawBackground(QPainter* painter, const QRectF& rect)
|
||||
{
|
||||
FrequencyPlotView::drawBackground(painter, rect);
|
||||
|
||||
painter->setRenderHint(QPainter::Antialiasing, true);
|
||||
AnalysisPlotScene* s = qobject_cast<AnalysisPlotScene*>(scene());
|
||||
std::vector<FilterNode>& nodes = s->getNodes();
|
||||
GainIterator gainIterator(nodes);
|
||||
QPainterPath path;
|
||||
bool first = true;
|
||||
double lastDb = -1000;
|
||||
for(int x = rect.left() - 1; x <= rect.right() + 1; x++)
|
||||
{
|
||||
double hz = s->xToHz(x);
|
||||
double db = gainIterator.gainAt(hz);
|
||||
double y = s->dbToY(db);
|
||||
if(db == lastDb)
|
||||
y = floor(y) + 0.5;
|
||||
lastDb = db;
|
||||
if(first)
|
||||
{
|
||||
path.moveTo(x, y);
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
path.lineTo(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
path.lineTo(rect.right() + 1, rect.bottom() + 1);
|
||||
path.lineTo(rect.left() - 1, rect.bottom() + 1);
|
||||
|
||||
double thresholdY = s->dbToY(0);
|
||||
if(rect.top() < thresholdY)
|
||||
{
|
||||
QPainterPath rectPath;
|
||||
rectPath.addRect(rect.left(), rect.top(), rect.width(), min(thresholdY - rect.top(), rect.height()));
|
||||
QPainterPath clippingPath = path.intersected(rectPath);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(Qt::red);
|
||||
painter->drawPath(clippingPath);
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
}
|
||||
|
||||
painter->setPen(Qt::black);
|
||||
painter->drawPath(path);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
This file is part of EqualizerAPO, a system-wide equalizer.
|
||||
Copyright (C) 2015 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/widgets/FrequencyPlotView.h"
|
||||
|
||||
class AnalysisPlotView : public FrequencyPlotView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AnalysisPlotView(QWidget* parent = NULL);
|
||||
|
||||
protected:
|
||||
void drawBackground(QPainter* painter, const QRectF& rect) override;
|
||||
};
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
This file is part of EqualizerAPO, a system-wide equalizer.
|
||||
Copyright (C) 2015 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 <QElapsedTimer>
|
||||
|
||||
#include "FilterEngine.h"
|
||||
#include "AnalysisThread.h"
|
||||
|
||||
AnalysisThread::AnalysisThread()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
AnalysisThread::~AnalysisThread()
|
||||
{
|
||||
mutex.lock();
|
||||
quit = true;
|
||||
condition.wakeAll();
|
||||
mutex.unlock();
|
||||
|
||||
wait();
|
||||
|
||||
if(resultFreqData != NULL)
|
||||
fftwf_free(resultFreqData);
|
||||
|
||||
if(buf != NULL)
|
||||
delete buf;
|
||||
if(buf2 != NULL)
|
||||
delete buf2;
|
||||
if(timeData != NULL)
|
||||
fftwf_free(timeData);
|
||||
if(freqData != NULL)
|
||||
fftwf_free(freqData);
|
||||
if(planForward != NULL)
|
||||
fftwf_destroy_plan(planForward);
|
||||
}
|
||||
|
||||
void AnalysisThread::setParameters(DeviceAPOInfo* device, int channelMask, int channelIndex, QString configPath, int frameCount)
|
||||
{
|
||||
QMutexLocker mutexLocker(&mutex);
|
||||
this->device = *device;
|
||||
this->channelMask = channelMask;
|
||||
this->channelIndex = channelIndex;
|
||||
this->configPath = configPath;
|
||||
this->frameCount = frameCount;
|
||||
|
||||
condition.wakeAll();
|
||||
}
|
||||
|
||||
void AnalysisThread::beginGetResult()
|
||||
{
|
||||
mutex.lock();
|
||||
}
|
||||
|
||||
void AnalysisThread::endGetResult()
|
||||
{
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
fftwf_complex* AnalysisThread::getFreqData() const
|
||||
{
|
||||
return resultFreqData;
|
||||
}
|
||||
|
||||
int AnalysisThread::getFreqDataLength() const
|
||||
{
|
||||
return freqDataLength;
|
||||
}
|
||||
|
||||
int AnalysisThread::getFreqDataSampleRate() const
|
||||
{
|
||||
return freqDataSampleRate;
|
||||
}
|
||||
|
||||
double AnalysisThread::getPeakGain() const
|
||||
{
|
||||
return peakGain;
|
||||
}
|
||||
|
||||
int AnalysisThread::getLatency() const
|
||||
{
|
||||
return latency;
|
||||
}
|
||||
|
||||
double AnalysisThread::getInitializationTime() const
|
||||
{
|
||||
return initializationTime;
|
||||
}
|
||||
|
||||
double AnalysisThread::getProcessingTime() const
|
||||
{
|
||||
return processingTime;
|
||||
}
|
||||
|
||||
int AnalysisThread::getProcessedFrames() const
|
||||
{
|
||||
return processedFrames;
|
||||
}
|
||||
|
||||
void AnalysisThread::run()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
mutex.lock();
|
||||
if(!quit && this->frameCount == 0)
|
||||
condition.wait(&mutex);
|
||||
if(quit)
|
||||
{
|
||||
mutex.unlock();
|
||||
break;
|
||||
}
|
||||
|
||||
DeviceAPOInfo device = this->device;
|
||||
int channelMask = this->channelMask;
|
||||
int channelIndex = this->channelIndex;
|
||||
QString configPath = this->configPath;
|
||||
int frameCount = this->frameCount;
|
||||
this->frameCount = 0;
|
||||
mutex.unlock();
|
||||
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
|
||||
unsigned channelCount = device.channelCount;
|
||||
if(channelMask != 0 && channelMask != device.channelMask)
|
||||
{
|
||||
channelCount = 0;
|
||||
for(int i = 0; i < 31; i++)
|
||||
{
|
||||
int channelPos = 1 << i;
|
||||
if(channelMask & channelPos)
|
||||
channelCount++;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned sampleRate = device.sampleRate;
|
||||
|
||||
qint64 startTime = timer.nsecsElapsed();
|
||||
FilterEngine engine;
|
||||
engine.setDeviceInfo(device.isInput, true, device.deviceName, device.connectionName, device.deviceGuid);
|
||||
engine.initialize(sampleRate, channelCount, channelCount, channelCount, channelMask, frameCount, configPath.toStdWString());
|
||||
double initializationTime = (timer.nsecsElapsed() - startTime) / 1e6;
|
||||
|
||||
if(frameCount != lastFrameCount || channelCount != lastChannelCount)
|
||||
{
|
||||
if(buf != NULL)
|
||||
delete buf;
|
||||
buf = new float[frameCount * channelCount];
|
||||
memset(buf, 0, frameCount * channelCount * sizeof(float));
|
||||
|
||||
if(buf2 != NULL)
|
||||
delete buf2;
|
||||
buf2 = new float[frameCount * channelCount];
|
||||
}
|
||||
for(unsigned i = 0; i < channelCount; i++)
|
||||
buf[i] = 1.0f;
|
||||
|
||||
if(frameCount != lastFrameCount)
|
||||
{
|
||||
if(timeData != NULL)
|
||||
fftwf_free(timeData);
|
||||
timeData = fftwf_alloc_real(frameCount);
|
||||
|
||||
if(freqData != NULL)
|
||||
fftwf_free(freqData);
|
||||
freqData = fftwf_alloc_complex(frameCount);
|
||||
|
||||
if(planForward != NULL)
|
||||
fftwf_destroy_plan(planForward);
|
||||
planForward = fftwf_plan_dft_r2c_1d(frameCount, timeData, freqData, FFTW_ESTIMATE);
|
||||
}
|
||||
|
||||
lastFrameCount = frameCount;
|
||||
lastChannelCount = channelCount;
|
||||
|
||||
int latency = 0;
|
||||
int startFrame = -1;
|
||||
double processingTime = 0.0;
|
||||
int processedFrames = 0;
|
||||
while(true)
|
||||
{
|
||||
qint64 startTime = timer.nsecsElapsed();
|
||||
engine.process(buf2, buf, frameCount);
|
||||
processingTime += (timer.nsecsElapsed() - startTime) / 1e6;
|
||||
processedFrames += frameCount;
|
||||
|
||||
if(startFrame != -1)
|
||||
{
|
||||
for(int i = 0; i < startFrame; i++)
|
||||
{
|
||||
timeData[frameCount - startFrame + i] = buf2[i * channelCount + channelIndex];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
for(int i = 0; i < frameCount; i++)
|
||||
{
|
||||
float s = buf2[i * channelCount + channelIndex];
|
||||
if(abs(s) > 1e-5f)
|
||||
{
|
||||
startFrame = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(startFrame != -1)
|
||||
{
|
||||
for(int i = 0; i < frameCount - startFrame; i++)
|
||||
{
|
||||
timeData[i] = buf2[(startFrame + i) * channelCount + channelIndex];
|
||||
}
|
||||
|
||||
if(startFrame == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if(latency == 0)
|
||||
{
|
||||
for(unsigned i = 0; i < channelCount; i++)
|
||||
buf[i] = 0.0f;
|
||||
}
|
||||
|
||||
if(startFrame == -1)
|
||||
latency += frameCount;
|
||||
}
|
||||
latency += startFrame;
|
||||
|
||||
fftwf_execute(planForward);
|
||||
|
||||
double peakGain = -DBL_MAX;
|
||||
|
||||
for(int i = 0; i < frameCount; i++)
|
||||
{
|
||||
float sqrGain = freqData[i][0] * freqData[i][0] + freqData[i][1] * freqData[i][1];
|
||||
if(sqrGain > peakGain)
|
||||
peakGain = sqrGain;
|
||||
}
|
||||
peakGain = sqrt(peakGain);
|
||||
peakGain = log10(peakGain) * 20.0;
|
||||
|
||||
mutex.lock();
|
||||
if(this->freqDataLength != frameCount)
|
||||
{
|
||||
if(resultFreqData != NULL)
|
||||
fftwf_free(resultFreqData);
|
||||
resultFreqData = fftwf_alloc_complex(frameCount);
|
||||
}
|
||||
memcpy(resultFreqData, freqData, frameCount * sizeof(fftwf_complex));
|
||||
this->freqDataLength = frameCount;
|
||||
this->freqDataSampleRate = sampleRate;
|
||||
this->latency = latency;
|
||||
this->peakGain = peakGain;
|
||||
this->initializationTime = initializationTime;
|
||||
this->processingTime = processingTime;
|
||||
this->processedFrames = processedFrames;
|
||||
mutex.unlock();
|
||||
|
||||
qDebug("Analysis took %.1f ms", timer.nsecsElapsed() / 1e6);
|
||||
|
||||
emit analysisFinished();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
This file is part of EqualizerAPO, a system-wide equalizer.
|
||||
Copyright (C) 2015 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 <QThread>
|
||||
#include <QWaitCondition>
|
||||
#include <fftw3.h>
|
||||
|
||||
#include "DeviceAPOInfo.h"
|
||||
|
||||
class AnalysisThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AnalysisThread();
|
||||
~AnalysisThread();
|
||||
void setParameters(DeviceAPOInfo* device, int channelMask, int channelIndex, QString configPath, int frameCount);
|
||||
void beginGetResult();
|
||||
void endGetResult();
|
||||
|
||||
fftwf_complex* getFreqData() const;
|
||||
int getFreqDataLength() const;
|
||||
int getFreqDataSampleRate() const;
|
||||
double getPeakGain() const;
|
||||
int getLatency() const;
|
||||
double getInitializationTime() const;
|
||||
double getProcessingTime() const;
|
||||
int getProcessedFrames() const;
|
||||
|
||||
signals:
|
||||
void analysisFinished();
|
||||
|
||||
protected:
|
||||
void run() override;
|
||||
|
||||
private:
|
||||
QMutex mutex;
|
||||
QWaitCondition condition;
|
||||
bool quit = false;
|
||||
|
||||
// input
|
||||
DeviceAPOInfo device;
|
||||
int channelMask;
|
||||
int channelIndex;
|
||||
QString configPath;
|
||||
int frameCount = 0;
|
||||
|
||||
// output
|
||||
fftwf_complex* resultFreqData = NULL;
|
||||
int freqDataLength = 0;
|
||||
int freqDataSampleRate;
|
||||
double peakGain;
|
||||
int latency;
|
||||
double initializationTime;
|
||||
double processingTime;
|
||||
int processedFrames;
|
||||
|
||||
// internal (not protected by mutex)
|
||||
int lastFrameCount = -1;
|
||||
int lastChannelCount = -1;
|
||||
float* buf = NULL;
|
||||
float* buf2 = NULL;
|
||||
float* timeData = NULL;
|
||||
fftwf_complex* freqData = NULL;
|
||||
fftwf_plan planForward = NULL;
|
||||
};
|
||||
+61
-13
@@ -13,8 +13,9 @@ TEMPLATE = app
|
||||
|
||||
PRECOMPILED_HEADER = stable.h
|
||||
QMAKE_CXXFLAGS_WARN_ON -= -w34100
|
||||
QMAKE_LFLAGS += /STACK:32000000
|
||||
|
||||
DEFINES += NO_FILTERENGINE
|
||||
DEFINES += _UNICODE
|
||||
|
||||
SOURCES += main.cpp\
|
||||
../helpers/LogHelper.cpp \
|
||||
@@ -88,9 +89,29 @@ SOURCES += main.cpp\
|
||||
helpers/DisableWheelFilter.cpp \
|
||||
widgets/EscapableLineEdit.cpp \
|
||||
MainWindow.cpp \
|
||||
guis/StageFilterGUI.cpp \
|
||||
guis/StageFilterGUIFactory.cpp \
|
||||
guis/ExpressionFilterGUIFactory.cpp
|
||||
guis/StageFilterGUI.cpp \
|
||||
guis/StageFilterGUIFactory.cpp \
|
||||
guis/ExpressionFilterGUIFactory.cpp \
|
||||
widgets/ResizeCorner.cpp \
|
||||
AnalysisPlotView.cpp \
|
||||
AnalysisPlotScene.cpp \
|
||||
../FilterEngine.cpp \
|
||||
../FilterConfiguration.cpp \
|
||||
../filters/ChannelFilterFactory.cpp \
|
||||
../filters/ExpressionFilterFactory.cpp \
|
||||
../filters/IfFilterFactory.cpp \
|
||||
../filters/StageFilterFactory.cpp \
|
||||
../filters/ConvolutionFilterFactory.cpp \
|
||||
../filters/IIRFilter.cpp \
|
||||
../filters/IIRFilterFactory.cpp \
|
||||
../filters/IncludeFilterFactory.cpp \
|
||||
../filters/ChannelFilter.cpp \
|
||||
../filters/ConvolutionFilter.cpp \
|
||||
../parser/RegexFunctions.cpp \
|
||||
../parser/RegistryFunctions.cpp \
|
||||
../parser/StringOperators.cpp \
|
||||
AnalysisThread.cpp \
|
||||
widgets/ExponentialSpinBox.cpp
|
||||
|
||||
HEADERS += \
|
||||
../helpers/LogHelper.h \
|
||||
@@ -168,9 +189,29 @@ HEADERS += \
|
||||
../version.h \
|
||||
../stdafx.h \
|
||||
MainWindow.h \
|
||||
guis/StageFilterGUI.h \
|
||||
guis/StageFilterGUIFactory.h \
|
||||
guis/ExpressionFilterGUIFactory.h
|
||||
guis/StageFilterGUI.h \
|
||||
guis/StageFilterGUIFactory.h \
|
||||
guis/ExpressionFilterGUIFactory.h \
|
||||
widgets/ResizeCorner.h \
|
||||
AnalysisPlotView.h \
|
||||
AnalysisPlotScene.h \
|
||||
../FilterEngine.h \
|
||||
../FilterConfiguration.h \
|
||||
../filters/ChannelFilterFactory.h \
|
||||
../filters/ExpressionFilterFactory.h \
|
||||
../filters/IfFilterFactory.h \
|
||||
../filters/StageFilterFactory.h \
|
||||
../filters/ConvolutionFilterFactory.h \
|
||||
../filters/IIRFilter.h \
|
||||
../filters/IIRFilterFactory.h \
|
||||
../filters/IncludeFilterFactory.h \
|
||||
../filters/ChannelFilter.h \
|
||||
../filters/ConvolutionFilter.h \
|
||||
../parser/RegexFunctions.h \
|
||||
../parser/RegistryFunctions.h \
|
||||
../parser/StringOperators.h \
|
||||
AnalysisThread.h \
|
||||
widgets/ExponentialSpinBox.h
|
||||
|
||||
FORMS += \
|
||||
guis/PreampFilterGUI.ui \
|
||||
@@ -188,14 +229,21 @@ FORMS += \
|
||||
guis/GraphicEQFilterGUI.ui \
|
||||
guis/ConvolutionFilterGUI.ui \
|
||||
MainWindow.ui \
|
||||
guis/StageFilterGUI.ui
|
||||
guis/StageFilterGUI.ui
|
||||
|
||||
INCLUDEPATH += $$PWD/.. "C:/Program Files/libsndfile/include" "C:/Program Files/fftw3"
|
||||
LIBS += advapi32.lib version.lib ole32.lib libsndfile-1.lib libfftw3f-3.lib
|
||||
contains(QT_ARCH, x86_64) {
|
||||
QMAKE_LIBDIR += "C:/Program Files/libsndfile/lib" "C:/Program Files/fftw3"
|
||||
INCLUDEPATH += $$PWD/.. "C:/Program Files/libsndfile/include" "C:/Program Files/fftw3" "C:/Program Files/muparserx_v3_0_1/parser"
|
||||
LIBS += advapi32.lib version.lib ole32.lib Shlwapi.lib libsndfile-1.lib libfftw3f-3.lib
|
||||
|
||||
build_pass:CONFIG(debug, debug|release) {
|
||||
LIBS += muparserxd.lib
|
||||
} else {
|
||||
QMAKE_LIBDIR += "C:/Program Files (x86)/libsndfile/lib" "C:/Program Files (x86)/fftw3"
|
||||
LIBS += muparserx.lib
|
||||
}
|
||||
|
||||
contains(QT_ARCH, x86_64) {
|
||||
QMAKE_LIBDIR += "C:/Program Files/libsndfile/lib" "C:/Program Files/fftw3" "C:/Program Files/muparserx_v3_0_1/lib64"
|
||||
} else {
|
||||
QMAKE_LIBDIR += "C:/Program Files (x86)/libsndfile/lib" "C:/Program Files (x86)/fftw3" "C:/Program Files/muparserx_v3_0_1/lib"
|
||||
}
|
||||
|
||||
RESOURCES += \
|
||||
|
||||
+2
-1
@@ -12,7 +12,7 @@
|
||||
<file>icons/16x16/accessories-text-editor.png</file>
|
||||
<file>icons/16x16/list-add-green.png</file>
|
||||
<file>icons/16x16/list-remove-red.png</file>
|
||||
<file>icons/mirror_response.png</file>
|
||||
<file>icons/invert_response.png</file>
|
||||
<file>icons/normalize_response.png</file>
|
||||
<file>icons/power_off.png</file>
|
||||
<file>icons/power_on.png</file>
|
||||
@@ -22,5 +22,6 @@
|
||||
<file>translations/qtbase_de.qm</file>
|
||||
<file>icons/16x16/go-up.png</file>
|
||||
<file>icons/reset_response.png</file>
|
||||
<file>icons/resize_corner.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
+38
-1
@@ -436,6 +436,38 @@ void FilterTable::openConfig(QString path)
|
||||
mainWindow->load(path);
|
||||
}
|
||||
|
||||
int FilterTable::getPreferredWidth()
|
||||
{
|
||||
if(scrollArea == NULL)
|
||||
return width();
|
||||
|
||||
return scrollArea->viewport()->width();
|
||||
}
|
||||
|
||||
void FilterTable::updateSizeHints()
|
||||
{
|
||||
for(int i = 0; i < items.size(); i++)
|
||||
{
|
||||
FilterTableRow* tableRow = qobject_cast<FilterTableRow*>(gridLayout->itemAtPosition(i, 0)->widget());
|
||||
tableRow->updateGeometry();
|
||||
}
|
||||
}
|
||||
|
||||
QSize FilterTable::minimumSizeHint() const
|
||||
{
|
||||
QSize size = QWidget::minimumSizeHint();
|
||||
if(size.height() < minimumHeightHint)
|
||||
size.setHeight(minimumHeightHint);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void FilterTable::setMinimumHeightHint(int height)
|
||||
{
|
||||
minimumHeightHint = height;
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void FilterTable::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
if(event->buttons() & Qt::LeftButton )
|
||||
@@ -723,9 +755,9 @@ void FilterTable::wheelEvent(QWheelEvent * event)
|
||||
|
||||
bool FilterTable::eventFilter(QObject* obj, QEvent* event)
|
||||
{
|
||||
QEvent::Type type = event->type();
|
||||
if(scrollingNow)
|
||||
{
|
||||
QEvent::Type type = event->type();
|
||||
if(type == QEvent::Wheel)
|
||||
{
|
||||
QWidget* widget = qobject_cast<QWidget*>(obj);
|
||||
@@ -747,6 +779,11 @@ bool FilterTable::eventFilter(QObject* obj, QEvent* event)
|
||||
}
|
||||
}
|
||||
|
||||
if(obj == scrollArea && type == QEvent::Resize)
|
||||
{
|
||||
updateSizeHints();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -79,6 +79,12 @@ public:
|
||||
|
||||
void openConfig(QString path);
|
||||
|
||||
int getPreferredWidth();
|
||||
void updateSizeHints();
|
||||
|
||||
QSize minimumSizeHint() const override;
|
||||
void setMinimumHeightHint(int height);
|
||||
|
||||
signals:
|
||||
void linesChanged();
|
||||
|
||||
@@ -123,6 +129,7 @@ private:
|
||||
DeviceAPOInfo* selectedDevice;
|
||||
int selectedChannelMask;
|
||||
QString configPath;
|
||||
int minimumHeightHint = 0;
|
||||
};
|
||||
|
||||
template<typename T> inline uint qHash(QList<T> list)
|
||||
|
||||
@@ -74,6 +74,15 @@ void FilterTableRow::editText()
|
||||
ui->actionEditText->trigger();
|
||||
}
|
||||
|
||||
QSize FilterTableRow::sizeHint() const
|
||||
{
|
||||
QSize size = QWidget::minimumSizeHint();
|
||||
int preferredWidth = table->getPreferredWidth();
|
||||
if(size.width() < preferredWidth)
|
||||
size = QSize(preferredWidth, size.height());
|
||||
return size;
|
||||
}
|
||||
|
||||
void FilterTableRow::mouseDoubleClickEvent(QMouseEvent*)
|
||||
{
|
||||
if(gui == NULL && ui->stackedWidget->currentIndex() == 1)
|
||||
|
||||
@@ -38,6 +38,7 @@ public:
|
||||
|
||||
QRect getHeaderRect();
|
||||
void editText();
|
||||
QSize sizeHint() const override;
|
||||
|
||||
protected:
|
||||
void mouseDoubleClickEvent(QMouseEvent*) override;
|
||||
|
||||
@@ -10,6 +10,12 @@
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Form</string>
|
||||
</property>
|
||||
|
||||
+167
-38
@@ -29,9 +29,9 @@
|
||||
#include <QFileInfo>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QProcess>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <QProcess>
|
||||
#include <windows.h>
|
||||
|
||||
#include "helpers/StringHelper.h"
|
||||
@@ -63,6 +63,8 @@ MainWindow::MainWindow(QDir configDir, QWidget *parent) :
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
LogHelper::set(stderr, true, false, false);
|
||||
|
||||
QString version = QString("%0.%1").arg(MAJOR).arg(MINOR);
|
||||
if(REVISION != 0)
|
||||
version += QString(".%0").arg(REVISION);
|
||||
@@ -123,11 +125,20 @@ MainWindow::MainWindow(QDir configDir, QWidget *parent) :
|
||||
deviceComboBox->addItem(QString::fromStdWString(apoInfo.connectionName) + " - " + QString::fromStdWString(apoInfo.deviceName), QVariant::fromValue(&apoInfo));
|
||||
|
||||
connect(channelConfigurationComboBox, SIGNAL(activated(int)), this, SLOT(channelConfigurationSelected(int)));
|
||||
|
||||
analysisPlotScene = new AnalysisPlotScene(ui->graphicsView);
|
||||
ui->graphicsView->setScene(analysisPlotScene);
|
||||
|
||||
analysisThread = new AnalysisThread;
|
||||
analysisThread->start();
|
||||
connect(analysisThread, SIGNAL(analysisFinished()), this, SLOT(updateAnalysisPanel()));
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
|
||||
delete analysisThread;
|
||||
}
|
||||
|
||||
void MainWindow::doChecks()
|
||||
@@ -304,6 +315,8 @@ void MainWindow::save(FilterTable* filterTable, QString path)
|
||||
CloseHandle(hFile);
|
||||
|
||||
qDebug("Saving took %.1f ms", timer.nsecsElapsed() / 1e6);
|
||||
|
||||
startAnalysis();
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent* event)
|
||||
@@ -366,6 +379,29 @@ void MainWindow::channelConfigurationSelected(int index)
|
||||
FilterTable* filterTable = qobject_cast<FilterTable*>(scrollArea->widget());
|
||||
filterTable->updateDeviceAndChannelMask(selectedDevice, channelMask);
|
||||
}
|
||||
|
||||
ui->analysisChannelComboBox->clear();
|
||||
|
||||
if(selectedDevice != NULL)
|
||||
{
|
||||
unsigned channelCount = selectedDevice->channelCount;
|
||||
if(channelMask != 0 && channelMask != selectedDevice->channelMask)
|
||||
{
|
||||
channelCount = 0;
|
||||
for(int i = 0; i < 31; i++)
|
||||
{
|
||||
int channelPos = 1 << i;
|
||||
if(channelMask & channelPos)
|
||||
channelCount++;
|
||||
}
|
||||
}
|
||||
|
||||
vector<wstring> channelNames = ChannelHelper::getChannelNames(channelCount, channelMask);
|
||||
for(wstring channelName : channelNames)
|
||||
{
|
||||
ui->analysisChannelComboBox->addItem(QString::fromStdWString(channelName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::linesChanged()
|
||||
@@ -400,22 +436,6 @@ void MainWindow::linesChanged()
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::getDeviceAndChannelMask(DeviceAPOInfo** selectedDevice, int* channelMask)
|
||||
{
|
||||
*selectedDevice = deviceComboBox->currentData().value<DeviceAPOInfo*>();
|
||||
if(*selectedDevice == NULL)
|
||||
*selectedDevice = defaultOutputDevice;
|
||||
|
||||
*channelMask = channelConfigurationComboBox->currentData().toInt();
|
||||
if(*channelMask == 0 && selectedDevice != NULL)
|
||||
{
|
||||
*channelMask = (*selectedDevice)->channelMask;
|
||||
|
||||
if(*channelMask == 0)
|
||||
*channelMask = ChannelHelper::getDefaultChannelMask((*selectedDevice)->channelCount);
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::on_tabWidget_tabCloseRequested(int index)
|
||||
{
|
||||
if(ui->tabWidget->tabText(index).endsWith('*'))
|
||||
@@ -549,27 +569,6 @@ void MainWindow::on_actionNew_triggered()
|
||||
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
|
||||
}
|
||||
|
||||
FilterTable* MainWindow::addTab(QString title, QString tooltip)
|
||||
{
|
||||
QScrollArea* scrollArea = new QScrollArea(ui->tabWidget);
|
||||
scrollArea->setWidgetResizable(true);
|
||||
FilterTable* filterTable = new FilterTable(this);
|
||||
scrollArea->setWidget(filterTable);
|
||||
filterTable->setAcceptDrops(true);
|
||||
filterTable->setFocusPolicy(Qt::WheelFocus);
|
||||
|
||||
int tabIndex = ui->tabWidget->addTab(scrollArea, title);
|
||||
ui->tabWidget->setTabToolTip(tabIndex, tooltip);
|
||||
|
||||
DeviceAPOInfo* selectedDevice;
|
||||
int channelMask;
|
||||
getDeviceAndChannelMask(&selectedDevice, &channelMask);
|
||||
filterTable->updateDeviceAndChannelMask(selectedDevice, channelMask);
|
||||
filterTable->initialize(scrollArea, outputDevices, inputDevices);
|
||||
|
||||
return filterTable;
|
||||
}
|
||||
|
||||
void MainWindow::on_actionCut_triggered()
|
||||
{
|
||||
QScrollArea* scrollArea = qobject_cast<QScrollArea*>(ui->tabWidget->currentWidget());
|
||||
@@ -630,3 +629,133 @@ void MainWindow::instantModeEnabled(bool enabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_tabWidget_currentChanged(int index)
|
||||
{
|
||||
startAnalysis();
|
||||
}
|
||||
|
||||
void MainWindow::on_startFromComboBox_activated(int index)
|
||||
{
|
||||
startAnalysis();
|
||||
}
|
||||
|
||||
void MainWindow::on_analysisChannelComboBox_activated(int index)
|
||||
{
|
||||
startAnalysis();
|
||||
}
|
||||
|
||||
void MainWindow::on_resolutionSpinBox_valueChanged(int value)
|
||||
{
|
||||
startAnalysis();
|
||||
}
|
||||
|
||||
void MainWindow::updateAnalysisPanel()
|
||||
{
|
||||
analysisThread->beginGetResult();
|
||||
int sampleRate = analysisThread->getFreqDataSampleRate();
|
||||
int latency = analysisThread->getLatency();
|
||||
analysisPlotScene->setFreqData(analysisThread->getFreqData(), analysisThread->getFreqDataLength(), sampleRate);
|
||||
|
||||
double peakGain = analysisThread->getPeakGain();
|
||||
ui->peakGainValueLabel->setText(tr("%0 dB").arg(peakGain, 0, 'f', 1));
|
||||
ui->peakGainValueLabel->setForegroundRole(peakGain > 0 ? QPalette::Dark : QPalette::WindowText);
|
||||
|
||||
ui->latencyValueLabel->setText(tr("%0 ms (%1 samples)").arg(latency * 1000.0 / sampleRate).arg(latency));
|
||||
|
||||
ui->initTimeValueLabel->setText(tr("%0 ms").arg(analysisThread->getInitializationTime(), 0, 'f', 1));
|
||||
|
||||
double cpuUsage = analysisThread->getProcessingTime() * 100.0 / (analysisThread->getProcessedFrames() * 1000.0 / sampleRate);
|
||||
ui->cpuUsageValueLabel->setText(tr("%0 % (one core)").arg(cpuUsage, 0, 'f', 1));
|
||||
ui->cpuUsageValueLabel->setForegroundRole(cpuUsage >= 20 ? (cpuUsage >= 50 ? QPalette::Dark : QPalette::Midlight) : QPalette::WindowText);
|
||||
|
||||
analysisThread->endGetResult();
|
||||
}
|
||||
|
||||
void MainWindow::on_mainToolBar_visibilityChanged(bool visible)
|
||||
{
|
||||
ui->actionToolbar->setChecked(visible);
|
||||
}
|
||||
|
||||
void MainWindow::on_analysisDockWidget_visibilityChanged(bool visible)
|
||||
{
|
||||
ui->actionAnalysisPanel->setChecked(visible);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionToolbar_triggered(bool checked)
|
||||
{
|
||||
ui->mainToolBar->setVisible(checked);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionAnalysisPanel_triggered(bool checked)
|
||||
{
|
||||
ui->analysisDockWidget->setVisible(checked);
|
||||
}
|
||||
|
||||
FilterTable* MainWindow::addTab(QString title, QString tooltip)
|
||||
{
|
||||
QScrollArea* scrollArea = new QScrollArea(ui->tabWidget);
|
||||
scrollArea->setWidgetResizable(true);
|
||||
FilterTable* filterTable = new FilterTable(this);
|
||||
scrollArea->setWidget(filterTable);
|
||||
filterTable->setAcceptDrops(true);
|
||||
filterTable->setFocusPolicy(Qt::WheelFocus);
|
||||
|
||||
int tabIndex = ui->tabWidget->addTab(scrollArea, title);
|
||||
ui->tabWidget->setTabToolTip(tabIndex, tooltip);
|
||||
|
||||
DeviceAPOInfo* selectedDevice;
|
||||
int channelMask;
|
||||
getDeviceAndChannelMask(&selectedDevice, &channelMask);
|
||||
filterTable->updateDeviceAndChannelMask(selectedDevice, channelMask);
|
||||
filterTable->initialize(scrollArea, outputDevices, inputDevices);
|
||||
|
||||
return filterTable;
|
||||
}
|
||||
|
||||
void MainWindow::getDeviceAndChannelMask(DeviceAPOInfo** selectedDevice, int* channelMask)
|
||||
{
|
||||
*selectedDevice = deviceComboBox->currentData().value<DeviceAPOInfo*>();
|
||||
if(*selectedDevice == NULL)
|
||||
*selectedDevice = defaultOutputDevice;
|
||||
|
||||
*channelMask = channelConfigurationComboBox->currentData().toInt();
|
||||
if(*channelMask == 0 && selectedDevice != NULL)
|
||||
{
|
||||
*channelMask = (*selectedDevice)->channelMask;
|
||||
|
||||
if(*channelMask == 0)
|
||||
*channelMask = ChannelHelper::getDefaultChannelMask((*selectedDevice)->channelCount);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::startAnalysis()
|
||||
{
|
||||
DeviceAPOInfo* selectedDevice;
|
||||
|
||||
int channelMask;
|
||||
getDeviceAndChannelMask(&selectedDevice, &channelMask);
|
||||
|
||||
if(selectedDevice != NULL)
|
||||
{
|
||||
QString configPath;
|
||||
|
||||
if(ui->startFromComboBox->currentIndex() == 1)
|
||||
{
|
||||
QScrollArea* scrollArea = qobject_cast<QScrollArea*>(ui->tabWidget->currentWidget());
|
||||
if(scrollArea != NULL)
|
||||
{
|
||||
FilterTable* filterTable = qobject_cast<FilterTable*>(scrollArea->widget());
|
||||
|
||||
if(filterTable->getConfigPath().length() > 0)
|
||||
configPath = filterTable->getConfigPath();
|
||||
}
|
||||
}
|
||||
|
||||
if(configPath.isEmpty())
|
||||
configPath = configDir.absoluteFilePath("config.txt");
|
||||
configPath = QDir::toNativeSeparators(configPath);
|
||||
|
||||
analysisThread->setParameters(selectedDevice, channelMask, ui->analysisChannelComboBox->currentIndex(), configPath, ui->resolutionSpinBox->value());
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#include "FilterTable.h"
|
||||
#include "DeviceAPOInfo.h"
|
||||
#include "Editor/AnalysisPlotScene.h"
|
||||
#include "Editor/AnalysisThread.h"
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
@@ -64,10 +66,21 @@ private slots:
|
||||
void on_actionCopy_triggered();
|
||||
|
||||
void instantModeEnabled(bool enabled);
|
||||
void on_tabWidget_currentChanged(int index);
|
||||
void on_startFromComboBox_activated(int index);
|
||||
void on_analysisChannelComboBox_activated(int index);
|
||||
void on_resolutionSpinBox_valueChanged(int value);
|
||||
void updateAnalysisPanel();
|
||||
|
||||
void on_mainToolBar_visibilityChanged(bool visible);
|
||||
void on_analysisDockWidget_visibilityChanged(bool visible);
|
||||
void on_actionToolbar_triggered(bool checked);
|
||||
void on_actionAnalysisPanel_triggered(bool checked);
|
||||
|
||||
private:
|
||||
FilterTable* addTab(QString title, QString tooltip);
|
||||
void getDeviceAndChannelMask(DeviceAPOInfo** selectedDevice, int* channelMask);
|
||||
void startAnalysis();
|
||||
|
||||
Ui::MainWindow *ui;
|
||||
|
||||
@@ -78,6 +91,8 @@ private:
|
||||
QList<DeviceAPOInfo> outputDevices;
|
||||
QList<DeviceAPOInfo> inputDevices;
|
||||
DeviceAPOInfo* defaultOutputDevice;
|
||||
AnalysisPlotScene* analysisPlotScene;
|
||||
AnalysisThread* analysisThread;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(DeviceAPOInfo*)
|
||||
@@ -71,10 +71,21 @@
|
||||
<addaction name="actionPaste"/>
|
||||
<addaction name="actionDelete"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuView">
|
||||
<property name="title">
|
||||
<string>View</string>
|
||||
</property>
|
||||
<addaction name="actionToolbar"/>
|
||||
<addaction name="actionAnalysisPanel"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuEdit"/>
|
||||
<addaction name="menuView"/>
|
||||
</widget>
|
||||
<widget class="QToolBar" name="mainToolBar">
|
||||
<property name="windowTitle">
|
||||
<string>Toolbar</string>
|
||||
</property>
|
||||
<attribute name="toolBarArea">
|
||||
<enum>TopToolBarArea</enum>
|
||||
</attribute>
|
||||
@@ -85,6 +96,452 @@
|
||||
<addaction name="actionOpen"/>
|
||||
<addaction name="actionSave"/>
|
||||
</widget>
|
||||
<widget class="QDockWidget" name="analysisDockWidget">
|
||||
<property name="windowTitle">
|
||||
<string>Analysis panel</string>
|
||||
</property>
|
||||
<attribute name="dockWidgetArea">
|
||||
<number>8</number>
|
||||
</attribute>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="horizontalSpacing">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="resolutionLabel">
|
||||
<property name="text">
|
||||
<string>FFT resolution:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="analysisChannelLabel">
|
||||
<property name="text">
|
||||
<string>Channel:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="analysisChannelComboBox"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="ExponentialSpinBox" name="resolutionSpinBox">
|
||||
<property name="correctionMode">
|
||||
<enum>QAbstractSpinBox::CorrectToNearestValue</enum>
|
||||
</property>
|
||||
<property name="keyboardTracking">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>128</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>8388608</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>65536</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="startFromLabel">
|
||||
<property name="text">
|
||||
<string>Start from:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="startFromComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>config.txt</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Current file</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Estimated properties</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="initTimeValueLabel">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="cpuUsageLabel">
|
||||
<property name="text">
|
||||
<string>CPU usage:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="initTimeLabel">
|
||||
<property name="text">
|
||||
<string>Init. time:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="cpuUsageValueLabel">
|
||||
<property name="palette">
|
||||
<palette>
|
||||
<active>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Midlight">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>127</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Dark">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Text">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="ButtonText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Midlight">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>127</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Dark">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Text">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="ButtonText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Midlight">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>127</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Dark">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Text">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="ButtonText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="latencyValueLabel">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="latencyLabel">
|
||||
<property name="text">
|
||||
<string>Latency: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="peakGainlabel">
|
||||
<property name="text">
|
||||
<string>Peak gain:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="peakGainValueLabel">
|
||||
<property name="palette">
|
||||
<palette>
|
||||
<active>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Dark">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Text">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="ButtonText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Dark">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Text">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="ButtonText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Dark">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Text">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="ButtonText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" rowspan="2">
|
||||
<widget class="AnalysisPlotView" name="graphicsView">
|
||||
<property name="mouseTracking">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="renderHints">
|
||||
<set>QPainter::Antialiasing|QPainter::TextAntialiasing</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<action name="actionNew">
|
||||
<property name="icon">
|
||||
<iconset resource="Editor.qrc">
|
||||
@@ -192,8 +649,36 @@
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionToolbar">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Toolbar</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAnalysisPanel">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Analysis panel</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>AnalysisPlotView</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>Editor/AnalysisPlotView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ExponentialSpinBox</class>
|
||||
<extends>QSpinBox</extends>
|
||||
<header>Editor/widgets/ExponentialSpinBox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="Editor.qrc"/>
|
||||
</resources>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "Editor/widgets/ResizeCorner.h"
|
||||
#include "helpers/ChannelHelper.h"
|
||||
#include "CopyFilterGUIForm.h"
|
||||
#include "CopyFilterGUI.h"
|
||||
@@ -24,7 +25,7 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
CopyFilterGUI::CopyFilterGUI(CopyFilter* filter) :
|
||||
CopyFilterGUI::CopyFilterGUI(CopyFilter* filter, FilterTable* filterTable) :
|
||||
ui(new Ui::CopyFilterGUI)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
@@ -35,6 +36,18 @@ CopyFilterGUI::CopyFilterGUI(CopyFilter* filter) :
|
||||
|
||||
ui->form->load(filter->getAssignments());
|
||||
|
||||
ResizeCorner* cornerWidget = new ResizeCorner(filterTable,
|
||||
QSize(0, 50), QSize(0, INT_MAX),
|
||||
[this]() {
|
||||
return QSize(0, ui->scrollArea->height());
|
||||
},
|
||||
[this](QSize size) {
|
||||
ui->scrollArea->setMinimumHeight(size.height());
|
||||
}, ui->scrollArea);
|
||||
cornerWidget->setCursor(Qt::SizeVerCursor);
|
||||
cornerWidget->setAutoFillBackground(true);
|
||||
ui->scrollArea->setCornerWidget(cornerWidget);
|
||||
|
||||
connect(scene, SIGNAL(updateModel()), this, SIGNAL(updateModel()));
|
||||
connect(scene, SIGNAL(updateChannels()), this, SIGNAL(updateChannels()));
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "filters/CopyFilter.h"
|
||||
#include "Editor/IFilterGUI.h"
|
||||
#include "CopyFilterGUIScene.h"
|
||||
#include "Editor/FilterTable.h"
|
||||
|
||||
namespace Ui {
|
||||
class CopyFilterGUI;
|
||||
@@ -32,7 +33,7 @@ class CopyFilterGUI : public IFilterGUI
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CopyFilterGUI(CopyFilter* filter);
|
||||
explicit CopyFilterGUI(CopyFilter* filter, FilterTable* filterTable);
|
||||
~CopyFilterGUI();
|
||||
|
||||
void configureChannels(std::vector<std::wstring>& channelNames) override;
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="documentMode">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="icon">
|
||||
@@ -79,6 +79,9 @@
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGraphicsView" name="graphicsView">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
||||
</property>
|
||||
@@ -121,6 +124,12 @@
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@@ -129,8 +138,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>366</width>
|
||||
<height>92</height>
|
||||
<width>348</width>
|
||||
<height>88</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
|
||||
@@ -26,6 +26,11 @@ CopyFilterGUIFactory::CopyFilterGUIFactory()
|
||||
{
|
||||
}
|
||||
|
||||
void CopyFilterGUIFactory::initialize(FilterTable* filterTable)
|
||||
{
|
||||
this->filterTable = filterTable;
|
||||
}
|
||||
|
||||
QList<FilterTemplate> CopyFilterGUIFactory::createFilterTemplates()
|
||||
{
|
||||
QList<FilterTemplate> list;
|
||||
@@ -44,7 +49,7 @@ IFilterGUI* CopyFilterGUIFactory::createFilterGUI(QString& command, QString& par
|
||||
if(!filters.empty())
|
||||
{
|
||||
CopyFilter* filter = (CopyFilter*)filters[0];
|
||||
result = new CopyFilterGUI(filter);
|
||||
result = new CopyFilterGUI(filter, filterTable);
|
||||
}
|
||||
|
||||
for(IFilter* f : filters)
|
||||
|
||||
@@ -28,6 +28,11 @@ class CopyFilterGUIFactory : public IFilterGUIFactory
|
||||
public:
|
||||
CopyFilterGUIFactory();
|
||||
|
||||
void initialize(FilterTable* filterTable) override;
|
||||
|
||||
QList<FilterTemplate> createFilterTemplates() override;
|
||||
IFilterGUI* createFilterGUI(QString& command, QString& parameters) override;
|
||||
|
||||
private:
|
||||
FilterTable* filterTable;
|
||||
};
|
||||
@@ -23,6 +23,8 @@
|
||||
#include <QTextStream>
|
||||
|
||||
#include "helpers/GainIterator.h"
|
||||
#include "Editor/widgets/ResizeCorner.h"
|
||||
#include "Editor/FilterTable.h"
|
||||
#include "GraphicEQFilterGUIView.h"
|
||||
#include "GraphicEQFilterGUI.h"
|
||||
#include "ui_GraphicEQFilterGUI.h"
|
||||
@@ -31,19 +33,29 @@ using namespace std;
|
||||
|
||||
QRegularExpression GraphicEQFilterGUI::numberRegEx("[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?");
|
||||
|
||||
GraphicEQFilterGUI::GraphicEQFilterGUI(GraphicEQFilter* filter, QString configPath) :
|
||||
GraphicEQFilterGUI::GraphicEQFilterGUI(GraphicEQFilter* filter, QString configPath, FilterTable* filterTable) :
|
||||
ui(new Ui::GraphicEQFilterGUI), configPath(configPath)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
setFixedHeight(150);
|
||||
|
||||
scene = new GraphicEQFilterGUIScene(ui->graphicsView);
|
||||
ui->graphicsView->setScene(scene);
|
||||
|
||||
ResizeCorner* cornerWidget = new ResizeCorner(filterTable,
|
||||
QSize(0, ui->graphicsView->minimumHeight()), QSize(10000 - ui->tableWidget->minimumWidth(), INT_MAX),
|
||||
[this]() {
|
||||
return QSize(10000 - ui->tableWidget->width(), ui->graphicsView->height());
|
||||
},
|
||||
[this](QSize size) {
|
||||
ui->tableWidget->setFixedWidth(10000 - size.width());
|
||||
ui->graphicsView->setFixedHeight(size.height());
|
||||
}, ui->graphicsView);
|
||||
ui->graphicsView->setCornerWidget(cornerWidget);
|
||||
ui->graphicsView->setFixedHeight(150);
|
||||
|
||||
ui->toolBar->addAction(ui->actionImport);
|
||||
ui->toolBar->addAction(ui->actionExport);
|
||||
ui->toolBar->addAction(ui->actionMirrorResponse);
|
||||
ui->toolBar->addAction(ui->actionInvertResponse);
|
||||
ui->toolBar->addAction(ui->actionNormalizeResponse);
|
||||
ui->toolBar->addAction(ui->actionResetResponse);
|
||||
|
||||
@@ -69,7 +81,7 @@ GraphicEQFilterGUI::GraphicEQFilterGUI(GraphicEQFilter* filter, QString configPa
|
||||
ui->radioButtonVar->click();
|
||||
}
|
||||
|
||||
ui->tableWidget->resizeColumnsToContents();
|
||||
ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
}
|
||||
|
||||
GraphicEQFilterGUI::~GraphicEQFilterGUI()
|
||||
@@ -77,7 +89,7 @@ GraphicEQFilterGUI::~GraphicEQFilterGUI()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void GraphicEQFilterGUI::store(QString& command, QString& parameters)
|
||||
void GraphicEQFilterGUI::store(QString & command, QString & parameters)
|
||||
{
|
||||
command = "GraphicEQ";
|
||||
|
||||
@@ -305,8 +317,6 @@ void GraphicEQFilterGUI::on_actionImport_triggered()
|
||||
{
|
||||
emit updateModel();
|
||||
}
|
||||
|
||||
ui->tableWidget->resizeColumnsToContents();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,7 +349,7 @@ void GraphicEQFilterGUI::on_actionExport_triggered()
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicEQFilterGUI::on_actionMirrorResponse_triggered()
|
||||
void GraphicEQFilterGUI::on_actionInvertResponse_triggered()
|
||||
{
|
||||
vector<FilterNode> newNodes = scene->getNodes();
|
||||
for(FilterNode& node : newNodes)
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "filters/GraphicEQFilter.h"
|
||||
#include "GraphicEQFilterGUIScene.h"
|
||||
|
||||
class FilterTable;
|
||||
|
||||
namespace Ui {
|
||||
class GraphicEQFilterGUI;
|
||||
}
|
||||
@@ -34,7 +36,7 @@ class GraphicEQFilterGUI : public IFilterGUI
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit GraphicEQFilterGUI(GraphicEQFilter* filter, QString configPath);
|
||||
explicit GraphicEQFilterGUI(GraphicEQFilter* filter, QString configPath, FilterTable* filterTable);
|
||||
~GraphicEQFilterGUI();
|
||||
|
||||
void store(QString& command, QString& parameters) override;
|
||||
@@ -54,13 +56,9 @@ private slots:
|
||||
void on_radioButtonVar_toggled(bool checked);
|
||||
|
||||
void on_actionImport_triggered();
|
||||
|
||||
void on_actionExport_triggered();
|
||||
|
||||
void on_actionMirrorResponse_triggered();
|
||||
|
||||
void on_actionInvertResponse_triggered();
|
||||
void on_actionNormalizeResponse_triggered();
|
||||
|
||||
void on_actionResetResponse_triggered();
|
||||
|
||||
private:
|
||||
|
||||
+158
-130
@@ -6,14 +6,17 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>442</width>
|
||||
<height>170</height>
|
||||
<width>623</width>
|
||||
<height>124</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout" rowstretch="1,0,0" columnstretch="0,1,0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1,0">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
@@ -26,134 +29,24 @@
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="horizontalSpacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Graphic EQ:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" rowspan="2">
|
||||
<widget class="QTableWidget" name="tableWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="palette">
|
||||
<palette>
|
||||
<active>
|
||||
<colorrole role="Highlight">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>51</red>
|
||||
<green>153</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="Highlight">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>122</red>
|
||||
<green>189</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="Highlight">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>51</red>
|
||||
<green>153</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>40</number>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderMinimumSectionSize">
|
||||
<number>40</number>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderDefaultSectionSize">
|
||||
<number>20</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Freq.</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Gain</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QToolBar" name="toolBar">
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" rowspan="3">
|
||||
<widget class="GraphicEQFilterGUIView" name="graphicsView">
|
||||
<property name="renderHints">
|
||||
<set>QPainter::Antialiasing|QPainter::TextAntialiasing</set>
|
||||
</property>
|
||||
<property name="dragMode">
|
||||
<enum>QGraphicsView::RubberBandDrag</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" rowspan="2">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Graphic EQ:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton15">
|
||||
<property name="text">
|
||||
@@ -180,6 +73,141 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="GraphicEQFilterGUIView" name="graphicsView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="mouseTracking">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="renderHints">
|
||||
<set>QPainter::Antialiasing|QPainter::TextAntialiasing</set>
|
||||
</property>
|
||||
<property name="dragMode">
|
||||
<enum>QGraphicsView::RubberBandDrag</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="tableWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="palette">
|
||||
<palette>
|
||||
<active>
|
||||
<colorrole role="Highlight">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>51</red>
|
||||
<green>153</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="Highlight">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>122</red>
|
||||
<green>189</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="Highlight">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>51</red>
|
||||
<green>153</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>10</number>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderMinimumSectionSize">
|
||||
<number>10</number>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderDefaultSectionSize">
|
||||
<number>20</number>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderMinimumSectionSize">
|
||||
<number>23</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Freq.</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Gain</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolBar" name="toolBar">
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="actionImport">
|
||||
<property name="icon">
|
||||
@@ -199,13 +227,13 @@
|
||||
<string>Export</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionMirrorResponse">
|
||||
<action name="actionInvertResponse">
|
||||
<property name="icon">
|
||||
<iconset resource="../Editor.qrc">
|
||||
<normaloff>:/icons/mirror_response.png</normaloff>:/icons/mirror_response.png</iconset>
|
||||
<normaloff>:/icons/invert_response.png</normaloff>:/icons/invert_response.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Mirror response</string>
|
||||
<string>Invert response</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionNormalizeResponse">
|
||||
|
||||
@@ -26,6 +26,11 @@ GraphicEQFilterGUIFactory::GraphicEQFilterGUIFactory()
|
||||
{
|
||||
}
|
||||
|
||||
void GraphicEQFilterGUIFactory::initialize(FilterTable* filterTable)
|
||||
{
|
||||
this->filterTable = filterTable;
|
||||
}
|
||||
|
||||
QList<FilterTemplate> GraphicEQFilterGUIFactory::createFilterTemplates()
|
||||
{
|
||||
QList<FilterTemplate> list;
|
||||
@@ -51,7 +56,7 @@ IFilterGUI* GraphicEQFilterGUIFactory::createFilterGUI(QString& command, QString
|
||||
if(!filters.empty())
|
||||
{
|
||||
GraphicEQFilter* filter = (GraphicEQFilter*)filters[0];
|
||||
result = new GraphicEQFilterGUI(filter, configPath);
|
||||
result = new GraphicEQFilterGUI(filter, configPath, filterTable);
|
||||
}
|
||||
|
||||
for(IFilter* f : filters)
|
||||
|
||||
@@ -28,6 +28,8 @@ class GraphicEQFilterGUIFactory : public IFilterGUIFactory
|
||||
public:
|
||||
GraphicEQFilterGUIFactory();
|
||||
|
||||
void initialize(FilterTable* filterTable) override;
|
||||
|
||||
QList<FilterTemplate> createFilterTemplates() override;
|
||||
|
||||
void startOfFile(const QString& configPath) override;
|
||||
@@ -35,4 +37,5 @@ public:
|
||||
|
||||
private:
|
||||
QString configPath;
|
||||
FilterTable* filterTable;
|
||||
};
|
||||
@@ -191,7 +191,7 @@ void GraphicEQFilterGUIScene::itemMoved(int index)
|
||||
hz = round(hz * 10) / 10;
|
||||
item->setHz(hz);
|
||||
}
|
||||
if(getZoom() < 4)
|
||||
if(getZoomY() < 4)
|
||||
db = round(db * 10) / 10;
|
||||
else
|
||||
db = round(db * 100) / 100;
|
||||
|
||||
File renamed without changes.
Binary file not shown.
|
Before Width: | Height: | Size: 432 B After Width: | Height: | Size: 424 B |
@@ -15,8 +15,8 @@
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
viewBox="0 0 16 16"
|
||||
sodipodi:docname="flat_response.svg"
|
||||
inkscape:export-filename="C:\Eigene Dateien\Entwickl\EqualizerAPO\trunk\Editor\guis\mirror_response.png"
|
||||
sodipodi:docname="reset_response.svg"
|
||||
inkscape:export-filename="C:\Eigene Dateien\Entwickl\EqualizerAPO\trunk\Editor\icons\reset_response.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
@@ -128,7 +128,7 @@
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="22.197802"
|
||||
inkscape:cx="-7.2042081"
|
||||
inkscape:cx="2.7742573"
|
||||
inkscape:cy="8"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
@@ -147,7 +147,7 @@
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
@@ -157,7 +157,7 @@
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="M -0.99108919,8 21.128211,8"
|
||||
d="M -0.99108919,8.5 21.128211,8.5"
|
||||
id="path6738"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
|
||||
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 195 B |
@@ -0,0 +1,242 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
id="svg4136"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
viewBox="0 0 16 16"
|
||||
sodipodi:docname="resize_corner.svg"
|
||||
inkscape:export-filename="C:\Eigene Dateien\Entwickl\EqualizerAPO\trunk\Editor\icons\resize_corner.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs4138">
|
||||
<linearGradient
|
||||
id="linearGradient8270"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop8272" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop8276" />
|
||||
</linearGradient>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutM"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="TriangleOutM"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4835"
|
||||
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(0.4)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutS"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="TriangleOutS"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4838"
|
||||
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(0.2)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Send"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow2Send"
|
||||
style="overflow:visible;"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4723"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
transform="scale(0.3) rotate(180) translate(-2.3,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleInS"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="TriangleInS"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4829"
|
||||
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(-0.2)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleInM"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="TriangleInM"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4826"
|
||||
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(-0.4)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Sstart"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="marker5044"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path5046"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(0.2) translate(6,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Sstart"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow2Sstart"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4720"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
transform="scale(0.3) translate(-2.3,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Sstart"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Sstart"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4702"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(0.2) translate(6,0)" />
|
||||
</marker>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient8270"
|
||||
id="linearGradient8750"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="13.337872"
|
||||
y1="13.887377"
|
||||
x2="15.968564"
|
||||
y2="15.711881" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="44.395604"
|
||||
inkscape:cx="6.225166"
|
||||
inkscape:cy="8.4597677"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1018"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata4141">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<circle
|
||||
style="fill:url(#linearGradient8750);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00600004;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="path7823-08"
|
||||
cx="14"
|
||||
cy="14"
|
||||
r="1"
|
||||
inkscape:tile-cx="14"
|
||||
inkscape:tile-cy="14"
|
||||
inkscape:tile-w="2"
|
||||
inkscape:tile-h="2"
|
||||
inkscape:tile-x0="13"
|
||||
inkscape:tile-y0="13" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#path7823-08"
|
||||
xlink:href="#path7823-08"
|
||||
transform="translate(0,-3)"
|
||||
id="use8018" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#path7823-08"
|
||||
xlink:href="#path7823-08"
|
||||
transform="translate(0,-6)"
|
||||
id="use8020" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#path7823-08"
|
||||
xlink:href="#path7823-08"
|
||||
transform="translate(-3,0)"
|
||||
id="use8022" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#path7823-08"
|
||||
xlink:href="#path7823-08"
|
||||
transform="translate(-3,-3)"
|
||||
id="use8024" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#path7823-08"
|
||||
xlink:href="#path7823-08"
|
||||
transform="translate(-6,0)"
|
||||
id="use8028" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.5 KiB |
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
This file is part of EqualizerAPO, a system-wide equalizer.
|
||||
Copyright (C) 2015 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 <cmath>
|
||||
#include "ExponentialSpinBox.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
ExponentialSpinBox::ExponentialSpinBox(QWidget* parent)
|
||||
: QSpinBox(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ExponentialSpinBox::stepBy(int steps)
|
||||
{
|
||||
qint64 v = value();
|
||||
if(steps > 0)
|
||||
{
|
||||
v <<= steps;
|
||||
if(v > maximum())
|
||||
v = maximum();
|
||||
}
|
||||
else
|
||||
{
|
||||
v >>= -steps;
|
||||
if(v < minimum())
|
||||
v = minimum();
|
||||
}
|
||||
|
||||
setValue((int)v);
|
||||
}
|
||||
|
||||
int ExponentialSpinBox::valueFromText(const QString& text) const
|
||||
{
|
||||
int value = QSpinBox::valueFromText(text);
|
||||
value = exp2(round(log2(value)));
|
||||
return value;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
This file is part of EqualizerAPO, a system-wide equalizer.
|
||||
Copyright (C) 2015 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 <QSpinBox>
|
||||
|
||||
class ExponentialSpinBox : public QSpinBox
|
||||
{
|
||||
public:
|
||||
ExponentialSpinBox(QWidget* parent = 0);
|
||||
|
||||
public:
|
||||
void stepBy(int steps) override;
|
||||
|
||||
protected:
|
||||
int valueFromText(const QString& text) const override;
|
||||
};
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <QPainter>
|
||||
#include <QMouseEvent>
|
||||
|
||||
#include "FrequencyPlotView.h"
|
||||
#include "FrequencyPlotHRuler.h"
|
||||
@@ -33,6 +34,7 @@ FrequencyPlotHRuler::FrequencyPlotHRuler(QWidget* parent) :
|
||||
void FrequencyPlotHRuler::paintEvent(QPaintEvent*)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
FrequencyPlotView* view = qobject_cast<FrequencyPlotView*>(parentWidget());
|
||||
FrequencyPlotScene* s = view->scene();
|
||||
QFontMetrics metrics = painter.fontMetrics();
|
||||
@@ -40,6 +42,7 @@ void FrequencyPlotHRuler::paintEvent(QPaintEvent*)
|
||||
|
||||
QPointF topLeft = view->mapToScene(0, 0);
|
||||
QPointF bottomRight = view->mapToScene(view->viewport()->width(), view->viewport()->height());
|
||||
int offsetLeft = view->viewportMargins().left();
|
||||
double fromHz = s->xToHz(topLeft.x());
|
||||
double toHz = s->xToHz(bottomRight.x());
|
||||
const vector<double>& bands = s->getBands();
|
||||
@@ -61,7 +64,7 @@ void FrequencyPlotHRuler::paintEvent(QPaintEvent*)
|
||||
else
|
||||
text = QString("%0k").arg(hz / 1000);
|
||||
if(metrics.width(text) + 2 < s->hzToX(hz + hzBase) - x)
|
||||
painter.drawText(x - topLeft.x() + height() + 1, 0, 0, height(), Qt::TextDontClip | Qt::AlignCenter, text);
|
||||
painter.drawText(x - topLeft.x() + offsetLeft + 1, 0, 0, height(), Qt::TextDontClip | Qt::AlignCenter, text);
|
||||
}
|
||||
|
||||
hz += hzBase;
|
||||
@@ -83,8 +86,50 @@ void FrequencyPlotHRuler::paintEvent(QPaintEvent*)
|
||||
text = QString("%0").arg(hz);
|
||||
else
|
||||
text = QString("%0k").arg(hz / 1000);
|
||||
painter.drawText(x - topLeft.x() + height() + 1, 0, 0, height(), Qt::TextDontClip | Qt::AlignCenter, text);
|
||||
painter.drawText(x - topLeft.x() + offsetLeft + 1, 0, 0, height(), Qt::TextDontClip | Qt::AlignCenter, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QPoint mousePos = view->getLastMousePos();
|
||||
if(!mousePos.isNull())
|
||||
{
|
||||
QPointF mouseScenePos = view->mapToScene(mousePos);
|
||||
|
||||
double hz = s->xToHz(mouseScenePos.x());
|
||||
double x = s->hzToX(hz);
|
||||
if(x != -1)
|
||||
{
|
||||
QString text = QString("%0").arg(hz, 0, 'f', 1);
|
||||
QFontMetrics metrics = painter.fontMetrics();
|
||||
QRectF rect = metrics.boundingRect(text);
|
||||
float center = x - topLeft.x() + offsetLeft + 1;
|
||||
rect = QRectF(center - ceil(rect.width() / 2) - 2 + 0.5, ceil(height() / 2) - ceil(rect.height() / 2) + 1.5, rect.width() + 3, rect.height());
|
||||
QPainterPath path;
|
||||
path.addRect(rect);
|
||||
QPainterPath topTriangle;
|
||||
topTriangle.moveTo(QPoint(center - 3, rect.top() + 1));
|
||||
topTriangle.lineTo(QPoint(center + 3, rect.top() + 1));
|
||||
topTriangle.lineTo(QPoint(center, rect.top() - 3));
|
||||
path = path.united(topTriangle);
|
||||
|
||||
painter.setPen(Qt::black);
|
||||
painter.setBrush(Qt::white);
|
||||
painter.drawPath(path);
|
||||
painter.setPen(Qt::blue);
|
||||
painter.drawText(center, 0, 0, height(), Qt::TextDontClip | Qt::AlignCenter, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FrequencyPlotHRuler::wheelEvent(QWheelEvent* event)
|
||||
{
|
||||
FrequencyPlotView* view = qobject_cast<FrequencyPlotView*>(parentWidget());
|
||||
view->zoom(event->angleDelta().y(), 0, event->x() - view->viewportMargins().left(), 0);
|
||||
}
|
||||
|
||||
void FrequencyPlotHRuler::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
FrequencyPlotView* view = qobject_cast<FrequencyPlotView*>(parentWidget());
|
||||
view->setLastMousePos(QPoint(event->x() - view->viewportMargins().left(), view->viewport()->height() - 1));
|
||||
}
|
||||
@@ -29,4 +29,6 @@ public:
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
void wheelEvent(QWheelEvent* event) override;
|
||||
void mouseMoveEvent(QMouseEvent* event) override;
|
||||
};
|
||||
@@ -48,7 +48,7 @@ void FrequencyPlotScene::addItem(FrequencyPlotItem* item)
|
||||
|
||||
double FrequencyPlotScene::xToHz(double x)
|
||||
{
|
||||
return pow(maxHz / minHz, x / zoom / maxX) * minHz;
|
||||
return pow(maxHz / minHz, x / zoomX / maxX) * minHz;
|
||||
}
|
||||
|
||||
double FrequencyPlotScene::hzToX(double hz)
|
||||
@@ -56,12 +56,12 @@ double FrequencyPlotScene::hzToX(double hz)
|
||||
if(hz < minHz || hz > maxHz)
|
||||
return -1;
|
||||
|
||||
return log(hz / minHz) / log(maxHz / minHz) * maxX * zoom;
|
||||
return log(hz / minHz) / log(maxHz / minHz) * maxX * zoomX;
|
||||
}
|
||||
|
||||
double FrequencyPlotScene::yToDb(double y)
|
||||
{
|
||||
return (minDb + (1 - y / zoom / maxY) * (maxDb - minDb));
|
||||
return (minDb + (1 - y / zoomY / maxY) * (maxDb - minDb));
|
||||
}
|
||||
|
||||
double FrequencyPlotScene::dbToY(double db)
|
||||
@@ -69,17 +69,23 @@ double FrequencyPlotScene::dbToY(double db)
|
||||
if(db < minDb || db > maxDb)
|
||||
return -1;
|
||||
|
||||
return (1 - (db - minDb) / (maxDb - minDb)) * maxY * zoom;
|
||||
return (1 - (db - minDb) / (maxDb - minDb)) * maxY * zoomY;
|
||||
}
|
||||
|
||||
double FrequencyPlotScene::getZoom() const
|
||||
double FrequencyPlotScene::getZoomX() const
|
||||
{
|
||||
return zoom;
|
||||
return zoomX;
|
||||
}
|
||||
|
||||
void FrequencyPlotScene::setZoom(double value)
|
||||
double FrequencyPlotScene::getZoomY() const
|
||||
{
|
||||
zoom = value;
|
||||
return zoomY;
|
||||
}
|
||||
|
||||
void FrequencyPlotScene::setZoom(double zoomX, double zoomY)
|
||||
{
|
||||
this->zoomX = zoomX;
|
||||
this->zoomY = zoomY;
|
||||
updateSceneRect();
|
||||
|
||||
for(QGraphicsItem* item : items())
|
||||
@@ -91,7 +97,7 @@ void FrequencyPlotScene::setZoom(double value)
|
||||
|
||||
void FrequencyPlotScene::updateSceneRect()
|
||||
{
|
||||
setSceneRect(0, 0, maxX * zoom, maxY * zoom);
|
||||
setSceneRect(0, 0, maxX * zoomX, maxY * zoomY);
|
||||
}
|
||||
|
||||
int FrequencyPlotScene::getBandCount() const
|
||||
|
||||
@@ -37,8 +37,9 @@ public:
|
||||
double yToDb(double y);
|
||||
double dbToY(double db);
|
||||
|
||||
double getZoom() const;
|
||||
void setZoom(double value);
|
||||
double getZoomX() const;
|
||||
double getZoomY() const;
|
||||
void setZoom(double zoomX, double zoomY);
|
||||
|
||||
int getBandCount() const;
|
||||
virtual void setBandCount(int value);
|
||||
@@ -54,6 +55,7 @@ protected:
|
||||
private:
|
||||
void updateSceneRect();
|
||||
|
||||
double zoom = 1.0;
|
||||
double zoomX = 1.0;
|
||||
double zoomY = 1.0;
|
||||
int bandCount = -1;
|
||||
};
|
||||
@@ -17,6 +17,8 @@
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <QWheelEvent>
|
||||
|
||||
#include "FrequencyPlotView.h"
|
||||
#include "FrequencyPlotScene.h"
|
||||
#include "FrequencyPlotVRuler.h"
|
||||
@@ -29,13 +31,13 @@ FrequencyPlotVRuler::FrequencyPlotVRuler(QWidget *parent) :
|
||||
void FrequencyPlotVRuler::paintEvent(QPaintEvent*)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
FrequencyPlotView* view = qobject_cast<FrequencyPlotView*>(parentWidget());
|
||||
FrequencyPlotScene* scene = view->scene();
|
||||
FrequencyPlotScene* s = view->scene();
|
||||
|
||||
QPointF topLeft = view->mapToScene(0, 0);
|
||||
QPointF bottomRight = view->mapToScene(view->viewport()->width(), view->viewport()->height());
|
||||
double dbHeight = abs(scene->yToDb(topLeft.y()) - scene->yToDb(bottomRight.y()));
|
||||
double dbStep = dbHeight / 4;
|
||||
double dbStep = abs(s->yToDb(0) - s->yToDb(30));
|
||||
|
||||
double dbBase = pow(10, floor(log10(dbStep)));
|
||||
if(dbStep >= 5 * dbBase)
|
||||
@@ -45,16 +47,58 @@ void FrequencyPlotVRuler::paintEvent(QPaintEvent*)
|
||||
else
|
||||
dbStep = dbBase;
|
||||
|
||||
double fromDb = floor(scene->yToDb(topLeft.y()) / dbStep) * dbStep;
|
||||
double toDb = ceil(scene->yToDb(bottomRight.y()) / dbStep) * dbStep;
|
||||
double fromDb = floor(s->yToDb(topLeft.y()) / dbStep) * dbStep;
|
||||
double toDb = ceil(s->yToDb(bottomRight.y()) / dbStep) * dbStep;
|
||||
|
||||
painter.setPen(QColor(50, 50, 50));
|
||||
for(double db = toDb; db <= fromDb; db += dbStep)
|
||||
{
|
||||
if(abs(db) < 1e-6)
|
||||
db = 0;
|
||||
double y = scene->dbToY(db);
|
||||
double y = s->dbToY(db);
|
||||
if(y != -1)
|
||||
painter.drawText(0, y - topLeft.y() - 1, width(), 0, Qt::TextDontClip | Qt::AlignCenter, QString("%0").arg(db));
|
||||
}
|
||||
|
||||
QPoint mousePos = view->getLastMousePos();
|
||||
if(!mousePos.isNull())
|
||||
{
|
||||
QPointF mouseScenePos = view->mapToScene(mousePos);
|
||||
|
||||
double db = s->yToDb(mouseScenePos.y());
|
||||
double y = s->dbToY(db);
|
||||
if(y != -1)
|
||||
{
|
||||
QString text = QString("%0").arg(db, 0, 'f', 1);
|
||||
QFontMetrics metrics = painter.fontMetrics();
|
||||
QRectF rect = metrics.boundingRect(text);
|
||||
float center = y - topLeft.y() - 1;
|
||||
rect = QRectF(ceil(width() / 2) - ceil(rect.width() / 2) - 2.5, center - rect.height() / 2 + 1, rect.width() + 3, rect.height());
|
||||
QPainterPath path;
|
||||
path.addRect(rect);
|
||||
QPainterPath rightTriangle;
|
||||
rightTriangle.moveTo(QPoint(rect.right(), center - 2));
|
||||
rightTriangle.lineTo(QPoint(rect.right(), center + 4));
|
||||
rightTriangle.lineTo(QPoint(rect.right() + 4, center + 1));
|
||||
path = path.united(rightTriangle);
|
||||
|
||||
painter.setPen(Qt::black);
|
||||
painter.setBrush(Qt::white);
|
||||
painter.drawPath(path);
|
||||
painter.setPen(Qt::blue);
|
||||
painter.drawText(0, center, width() - 2, 0, Qt::TextDontClip | Qt::AlignCenter, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FrequencyPlotVRuler::wheelEvent(QWheelEvent* event)
|
||||
{
|
||||
FrequencyPlotView* view = qobject_cast<FrequencyPlotView*>(parentWidget());
|
||||
view->zoom(0, event->angleDelta().y(), 0, event->y());
|
||||
}
|
||||
|
||||
void FrequencyPlotVRuler::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
FrequencyPlotView* view = qobject_cast<FrequencyPlotView*>(parentWidget());
|
||||
view->setLastMousePos(QPoint(0, min(event->y(), view->viewport()->height() - 1)));
|
||||
}
|
||||
@@ -29,4 +29,6 @@ public:
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
void wheelEvent(QWheelEvent* event) override;
|
||||
void mouseMoveEvent(QMouseEvent* event) override;
|
||||
};
|
||||
@@ -29,9 +29,11 @@ using namespace std;
|
||||
FrequencyPlotView::FrequencyPlotView(QWidget *parent) :
|
||||
QGraphicsView(parent)
|
||||
{
|
||||
setViewportMargins(20, 0, 0, 20);
|
||||
setViewportMargins(32, 0, 0, 20);
|
||||
hRuler = new FrequencyPlotHRuler(this);
|
||||
vRuler = new FrequencyPlotVRuler(this);
|
||||
hRuler->setMouseTracking(true);
|
||||
vRuler->setMouseTracking(true);
|
||||
}
|
||||
|
||||
FrequencyPlotScene* FrequencyPlotView::scene() const
|
||||
@@ -58,8 +60,7 @@ void FrequencyPlotView::drawBackground(QPainter* painter, const QRectF& drawRect
|
||||
FrequencyPlotScene* s = scene();
|
||||
QPointF topLeft = mapToScene(0, 0);
|
||||
QPointF bottomRight = mapToScene(viewport()->width(), viewport()->height());
|
||||
double dbHeight = abs(s->yToDb(topLeft.y()) - s->yToDb(bottomRight.y()));
|
||||
double dbStep = dbHeight / 4;
|
||||
double dbStep = abs(s->yToDb(0) - s->yToDb(30));
|
||||
|
||||
double dbBase = pow(10, floor(log10(dbStep)));
|
||||
if(dbStep >= 5 * dbBase)
|
||||
@@ -120,27 +121,57 @@ void FrequencyPlotView::updateHRuler()
|
||||
hRuler->update();
|
||||
}
|
||||
|
||||
void FrequencyPlotView::wheelEvent(QWheelEvent* event)
|
||||
QPoint FrequencyPlotView::getLastMousePos() const
|
||||
{
|
||||
return lastMousePos;
|
||||
}
|
||||
|
||||
void FrequencyPlotView::setLastMousePos(QPoint pos)
|
||||
{
|
||||
lastMousePos = pos;
|
||||
hRuler->update();
|
||||
vRuler->update();
|
||||
}
|
||||
|
||||
void FrequencyPlotView::zoom(int deltaX, int deltaY, int mouseX, int mouseY)
|
||||
{
|
||||
FrequencyPlotScene* s = scene();
|
||||
QPointF scenePos = mapToScene(event->pos());
|
||||
QPointF scenePos = mapToScene(mouseX, mouseY);
|
||||
double hz = s->xToHz(scenePos.x());
|
||||
double db = s->yToDb(scenePos.y());
|
||||
|
||||
qreal zoomFactor = pow(1.001, event->angleDelta().y());
|
||||
s->setZoom(max(0.5, min(30, s->getZoom() * zoomFactor)));
|
||||
qreal zoomFactorX = pow(1.001, deltaX);
|
||||
qreal zoomFactorY = pow(1.001, deltaY);
|
||||
double zoomX = max(0.5, min(30.0, s->getZoomX() * zoomFactorX));
|
||||
double zoomY = max(0.5, min(30.0, s->getZoomY() * zoomFactorY));
|
||||
s->setZoom(zoomX, zoomY);
|
||||
|
||||
double x = s->hzToX(hz);
|
||||
if(x != -1)
|
||||
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + round(x - scenePos.x()));
|
||||
double y = s->dbToY(db);
|
||||
if(y != -1)
|
||||
verticalScrollBar()->setValue(verticalScrollBar()->value() + round(y - scenePos.y()));
|
||||
if(deltaX != 0)
|
||||
{
|
||||
double x = s->hzToX(hz);
|
||||
if(x != -1)
|
||||
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + round(x - scenePos.x()));
|
||||
}
|
||||
|
||||
if(deltaY != 0)
|
||||
{
|
||||
double y = s->dbToY(db);
|
||||
if(y != -1)
|
||||
verticalScrollBar()->setValue(verticalScrollBar()->value() + round(y - scenePos.y()));
|
||||
}
|
||||
|
||||
resetCachedContent();
|
||||
viewport()->update();
|
||||
hRuler->update();
|
||||
vRuler->update();
|
||||
if(deltaX != 0)
|
||||
hRuler->update();
|
||||
if(deltaY != 0)
|
||||
vRuler->update();
|
||||
}
|
||||
|
||||
void FrequencyPlotView::wheelEvent(QWheelEvent* event)
|
||||
{
|
||||
int delta = event->angleDelta().y();
|
||||
zoom(delta, delta, event->x(), event->y());
|
||||
}
|
||||
|
||||
void FrequencyPlotView::scrollContentsBy(int dx, int dy)
|
||||
@@ -158,15 +189,16 @@ void FrequencyPlotView::resizeEvent(QResizeEvent* event)
|
||||
QGraphicsView::resizeEvent(event);
|
||||
|
||||
const QRect rect = viewport()->geometry();
|
||||
hRuler->setGeometry(rect.x() - 20, rect.y() + rect.height(), rect.width() + 20, 20);
|
||||
vRuler->setGeometry(rect.x() - 20, rect.y(), 20, rect.height() + 20);
|
||||
QMargins margins = viewportMargins();
|
||||
hRuler->setGeometry(rect.x() - margins.left(), rect.y() + rect.height(), rect.width() + margins.left(), margins.bottom());
|
||||
vRuler->setGeometry(rect.x() - margins.left(), rect.y(), margins.left(), rect.height() + margins.bottom());
|
||||
}
|
||||
|
||||
void FrequencyPlotView::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
QGraphicsView::mousePressEvent(event);
|
||||
|
||||
lastMousePos = event->pos();
|
||||
setLastMousePos(event->pos());
|
||||
}
|
||||
|
||||
void FrequencyPlotView::mouseMoveEvent(QMouseEvent* event)
|
||||
@@ -180,7 +212,12 @@ void FrequencyPlotView::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
QGraphicsView::mouseMoveEvent(event);
|
||||
}
|
||||
lastMousePos = event->pos();
|
||||
setLastMousePos(event->pos());
|
||||
}
|
||||
|
||||
void FrequencyPlotView::leaveEvent(QEvent*)
|
||||
{
|
||||
setLastMousePos(QPoint());
|
||||
}
|
||||
|
||||
void FrequencyPlotView::showEvent(QShowEvent* event)
|
||||
|
||||
@@ -38,12 +38,19 @@ public:
|
||||
|
||||
void updateHRuler();
|
||||
|
||||
QPoint getLastMousePos() const;
|
||||
void setLastMousePos(QPoint pos);
|
||||
using QGraphicsView::viewportMargins;
|
||||
|
||||
void zoom(int deltaX, int deltaY, int mouseX, int mouseY);
|
||||
|
||||
protected:
|
||||
void wheelEvent(QWheelEvent* event) override;
|
||||
void scrollContentsBy(int dx, int dy) override;
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
void mouseMoveEvent(QMouseEvent* event) override;
|
||||
void leaveEvent(QEvent*) override;
|
||||
void showEvent(QShowEvent* event) override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
This file is part of EqualizerAPO, a system-wide equalizer.
|
||||
Copyright (C) 2015 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 <QMouseEvent>
|
||||
|
||||
#include "ResizeCorner.h"
|
||||
|
||||
ResizeCorner::ResizeCorner(FilterTable* filterTable, QSize minimumSize, QSize maximumSize, std::function<QSize()> getFunc, std::function<void(QSize)> setFunc, QWidget *parent)
|
||||
: QLabel(parent), minimumSize(minimumSize), maximumSize(maximumSize), getFunc(getFunc), setFunc(setFunc), filterTable(filterTable)
|
||||
{
|
||||
setPixmap(QPixmap(":/icons/resize_corner.png"));
|
||||
setCursor(Qt::SizeFDiagCursor);
|
||||
}
|
||||
|
||||
void ResizeCorner::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
filterTable->setMinimumHeightHint(filterTable->height());
|
||||
QSize size = getFunc();
|
||||
offsetX = size.width() - event->globalX();
|
||||
offsetY = size.height() - event->globalY();
|
||||
}
|
||||
|
||||
void ResizeCorner::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
QSize size;
|
||||
size.setWidth(offsetX + event->globalPos().x());
|
||||
size.setHeight(offsetY + event->globalPos().y());
|
||||
size = size.expandedTo(minimumSize);
|
||||
size = size.boundedTo(maximumSize);
|
||||
setFunc(size);
|
||||
}
|
||||
|
||||
void ResizeCorner::mouseReleaseEvent(QMouseEvent*)
|
||||
{
|
||||
filterTable->setMinimumHeightHint(0);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
This file is part of EqualizerAPO, a system-wide equalizer.
|
||||
Copyright (C) 2015 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 <functional>
|
||||
#include <QLabel>
|
||||
|
||||
#include "Editor/FilterTable.h"
|
||||
|
||||
class ResizeCorner : public QLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ResizeCorner(FilterTable* filterTable, QSize minimumSize, QSize maximumSize,
|
||||
std::function<QSize()> getFunc, std::function<void(QSize)> setFunc, QWidget *parent = 0);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
void mouseMoveEvent(QMouseEvent* event) override;
|
||||
void mouseReleaseEvent(QMouseEvent*) override;
|
||||
|
||||
private:
|
||||
int offsetX;
|
||||
int offsetY;
|
||||
QSize minimumSize;
|
||||
QSize maximumSize;
|
||||
FilterTable* filterTable;
|
||||
std::function<QSize()> getFunc;
|
||||
std::function<void(QSize)> setFunc;
|
||||
};
|
||||
+8
-6
@@ -57,6 +57,8 @@ EqualizerAPO::EqualizerAPO(IUnknown* pUnkOuter)
|
||||
EqualizerAPO::~EqualizerAPO()
|
||||
{
|
||||
InterlockedDecrement(&instCount);
|
||||
|
||||
resetChild();
|
||||
}
|
||||
|
||||
HRESULT EqualizerAPO::QueryInterface(const IID& iid, void** ppv)
|
||||
@@ -156,7 +158,7 @@ HRESULT EqualizerAPO::Initialize(UINT32 cbDataSize, BYTE* pbyData)
|
||||
if(FAILED(hr))
|
||||
{
|
||||
LogF(L"Can't convert child apo guid string to guid");
|
||||
return hr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hr = CoCreateInstance(childGuid, NULL, CLSCTX_INPROC_SERVER, __uuidof(IAudioProcessingObject), (void**)&childAPO);
|
||||
@@ -164,7 +166,7 @@ HRESULT EqualizerAPO::Initialize(UINT32 cbDataSize, BYTE* pbyData)
|
||||
{
|
||||
LogF(L"Error in CoCreateInstance for child apo");
|
||||
resetChild();
|
||||
return hr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hr = childAPO->QueryInterface(__uuidof(IAudioProcessingObjectRT), (void**)&childRT);
|
||||
@@ -172,7 +174,7 @@ HRESULT EqualizerAPO::Initialize(UINT32 cbDataSize, BYTE* pbyData)
|
||||
{
|
||||
LogF(L"Error in QueryInterface for child apo RT");
|
||||
resetChild();
|
||||
return hr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hr = childAPO->QueryInterface(__uuidof(IAudioProcessingObjectConfiguration), (void**)&childCfg);
|
||||
@@ -180,7 +182,7 @@ HRESULT EqualizerAPO::Initialize(UINT32 cbDataSize, BYTE* pbyData)
|
||||
{
|
||||
LogF(L"Error in QueryInterface for child apo configuration");
|
||||
resetChild();
|
||||
return hr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hr = childAPO->Initialize(cbDataSize, pbyData);
|
||||
@@ -188,13 +190,13 @@ HRESULT EqualizerAPO::Initialize(UINT32 cbDataSize, BYTE* pbyData)
|
||||
{
|
||||
LogF(L"Error in Initialize of child apo");
|
||||
resetChild();
|
||||
return hr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
TraceF(L"Successfully created and initialized child APO");
|
||||
}
|
||||
|
||||
return hr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT EqualizerAPO::IsInputFormatSupported(IAudioMediaType* pOutputFormat,
|
||||
|
||||
+9
-6
@@ -127,7 +127,7 @@ void FilterEngine::setDeviceInfo(bool capture, bool postMixInstalled, const wstr
|
||||
this->deviceGuid = deviceGuid;
|
||||
}
|
||||
|
||||
void FilterEngine::initialize(float sampleRate, unsigned inputChannelCount, unsigned realChannelCount, unsigned outputChannelCount, unsigned channelMask, unsigned maxFrameCount)
|
||||
void FilterEngine::initialize(float sampleRate, unsigned inputChannelCount, unsigned realChannelCount, unsigned outputChannelCount, unsigned channelMask, unsigned maxFrameCount, const wstring& customPath)
|
||||
{
|
||||
EnterCriticalSection(&loadSection);
|
||||
|
||||
@@ -184,9 +184,9 @@ void FilterEngine::initialize(float sampleRate, unsigned inputChannelCount, unsi
|
||||
|
||||
if(configPath != L"")
|
||||
{
|
||||
loadConfig();
|
||||
loadConfig(customPath);
|
||||
|
||||
if(threadHandle == NULL)
|
||||
if(threadHandle == NULL && customPath.empty())
|
||||
{
|
||||
shutdownEvent = CreateEventW(NULL, true, false, NULL);
|
||||
threadHandle = CreateThread(NULL, 0, notificationThread, this, 0, NULL);
|
||||
@@ -199,7 +199,7 @@ void FilterEngine::initialize(float sampleRate, unsigned inputChannelCount, unsi
|
||||
LeaveCriticalSection(&loadSection);
|
||||
}
|
||||
|
||||
void FilterEngine::loadConfig()
|
||||
void FilterEngine::loadConfig(const wstring& customPath)
|
||||
{
|
||||
EnterCriticalSection(&loadSection);
|
||||
timer.start();
|
||||
@@ -226,7 +226,10 @@ void FilterEngine::loadConfig()
|
||||
addFilters(newFilters);
|
||||
}
|
||||
|
||||
loadConfig(configPath + L"\\config.txt");
|
||||
if(customPath.empty())
|
||||
loadConfigFile(configPath + L"\\config.txt");
|
||||
else
|
||||
loadConfigFile(customPath);
|
||||
|
||||
for(vector<IFilterFactory*>::const_iterator it = factories.cbegin(); it != factories.cend(); it++)
|
||||
{
|
||||
@@ -252,7 +255,7 @@ void FilterEngine::loadConfig()
|
||||
LeaveCriticalSection(&loadSection);
|
||||
}
|
||||
|
||||
void FilterEngine::loadConfig(const wstring& path)
|
||||
void FilterEngine::loadConfigFile(const wstring& path)
|
||||
{
|
||||
TraceF(L"Loading configuration from %s", path.c_str());
|
||||
|
||||
|
||||
+3
-3
@@ -40,9 +40,9 @@ public:
|
||||
|
||||
void setPreMix(bool preMix);
|
||||
void setDeviceInfo(bool capture, bool postMixInstalled, const std::wstring& deviceName, const std::wstring& connectionName, const std::wstring& deviceGuid);
|
||||
void initialize(float sampleRate, unsigned inputChannelCount, unsigned realChannelCount, unsigned outputChannelCount, unsigned channelMask, unsigned maxFrameCount);
|
||||
void loadConfig();
|
||||
void loadConfig(const std::wstring& path);
|
||||
void initialize(float sampleRate, unsigned inputChannelCount, unsigned realChannelCount, unsigned outputChannelCount, unsigned channelMask, unsigned maxFrameCount, const std::wstring& customPath = L"");
|
||||
void loadConfig(const std::wstring& customPath = L"");
|
||||
void loadConfigFile(const std::wstring& path);
|
||||
void watchRegistryKey(const std::wstring& key);
|
||||
void process(float *output, float *input, unsigned frameCount);
|
||||
|
||||
|
||||
+1
-1
@@ -165,7 +165,7 @@ Section "Install" SecInstall
|
||||
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
|
||||
;Create shortcuts
|
||||
CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Configuration editor.lnk" "$INSTDIR\Editor.exe"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Configuration Editor.lnk" "$INSTDIR\Editor.exe"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Configuration tutorial (online).lnk" "$INSTDIR\Configuration tutorial (online).url"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Configuration reference (online).lnk" "$INSTDIR\Configuration reference (online).url"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Configurator.lnk" "$INSTDIR\Configurator.exe"
|
||||
|
||||
@@ -56,7 +56,7 @@ vector<IFilter*> IncludeFilterFactory::createFilter(const wstring& configPath, w
|
||||
else
|
||||
includePath = value;
|
||||
|
||||
engine->loadConfig(includePath);
|
||||
engine->loadConfigFile(includePath);
|
||||
command = L"";
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user