diff --git a/sdrgui/CMakeLists.txt b/sdrgui/CMakeLists.txt
index c73f497d4..e2a9f60b5 100644
--- a/sdrgui/CMakeLists.txt
+++ b/sdrgui/CMakeLists.txt
@@ -37,6 +37,7 @@ set(sdrgui_SOURCES
gui/featuresdock.cpp
gui/featurepresetsdialog.cpp
gui/featurewindow.cpp
+ gui/fftwisdomdialog.cpp
gui/glscope.cpp
gui/glscopegui.cpp
gui/glshadercolors.cpp
@@ -125,6 +126,7 @@ set(sdrgui_HEADERS
gui/featuresdock.h
gui/featurepresetsdialog.h
gui/featurewindow.h
+ gui/fftwisdomdialog.h
gui/glscope.h
gui/glscopegui.h
gui/glshadercolors.h
@@ -199,6 +201,7 @@ set(sdrgui_FORMS
gui/fmpreemphasisdialog.ui
gui/featureadddialog.ui
gui/featurepresetsdialog.ui
+ gui/fftwisdomdialog.ui
gui/glscopegui.ui
gui/glspectrumgui.ui
gui/pluginsdialog.ui
diff --git a/sdrgui/gui/fftwisdomdialog.cpp b/sdrgui/gui/fftwisdomdialog.cpp
new file mode 100644
index 000000000..1a48496a2
--- /dev/null
+++ b/sdrgui/gui/fftwisdomdialog.cpp
@@ -0,0 +1,135 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2021 F4EXB //
+// written by Edouard Griffiths //
+// //
+// 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 as version 3 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 V3 for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program. If not, see . //
+///////////////////////////////////////////////////////////////////////////////////
+
+#include
+#include
+#include
+#include
+#include
+
+#include "fftwisdomdialog.h"
+#include "ui_fftwisdomdialog.h"
+
+FFTWisdomDialog::FFTWisdomDialog(QProcess *process, QWidget* parent) :
+ QDialog(parent),
+ ui(new Ui::FFTWisdomDialog),
+ m_process(process)
+{
+ ui->setupUi(this);
+
+ QString pathVar = qgetenv("PATH");
+ QStringList findPaths = pathVar.split(QDir::listSeparator());
+ findPaths.append(QCoreApplication::applicationDirPath());
+ QString exePath = QStandardPaths::findExecutable("fftwf-wisdom", findPaths);
+
+ if (exePath.length() != 0)
+ {
+ m_fftwExecPath = exePath;
+ ui->executable->setText(exePath);
+ }
+
+ updateArguments(3, false);
+}
+
+FFTWisdomDialog::~FFTWisdomDialog()
+{
+ delete ui;
+}
+
+void FFTWisdomDialog::on_showFileDialog_clicked()
+{
+ QFileDialog fileDialog(this, "Select FFTW Wisdom file generator");
+ fileDialog.setOptions(QFileDialog::DontUseNativeDialog);
+ fileDialog.selectFile(m_fftwExecPath);
+
+ if (fileDialog.exec() == QDialog::Accepted)
+ {
+ QStringList fileNames = fileDialog.selectedFiles();
+
+ if (fileNames.size() > 0) {
+ m_fftwExecPath = fileNames.at(0);
+ }
+ }
+}
+
+void FFTWisdomDialog::on_fftwMaxSize_currentIndexChanged(int index)
+{
+ updateArguments(index, ui->fftwReverse->isChecked());
+}
+
+void FFTWisdomDialog::on_fftwReverse_toggled(bool checked)
+{
+ updateArguments(ui->fftwMaxSize->currentIndex(), checked);
+}
+
+void FFTWisdomDialog::accept()
+{
+ m_process->start(m_fftwExecPath, m_fftwArguments);
+ qDebug("FFTWisdomDialog::accept: process started");
+ QDialog::accept();
+}
+
+void FFTWisdomDialog::reject()
+{
+ QDialog::reject();
+}
+
+void FFTWisdomDialog::processFinished(int exitCode, QProcess::ExitStatus exitStatus)
+{
+ qDebug("FFTWisdomDialog::processFinished: process finished rc=%d (%d)", exitCode, (int) exitStatus);
+
+ if ((exitCode != 0) || (exitStatus != QProcess::NormalExit))
+ {
+ QMessageBox::critical(this, "FFTW Wisdom", "fftwf-widdsom program failed");
+ }
+ else
+ {
+ QString log = m_process->readAllStandardOutput();
+ QMessageBox::information(this, "FFTW Wisdom", QString("Success\n%1").arg(log));
+
+ }
+
+ delete m_process;
+}
+
+void FFTWisdomDialog::updateArguments(int fftMaxLog2, bool includeReverse)
+{
+ QString filePath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
+ filePath += QDir::separator();
+ filePath += "fftw-wisdom";
+
+ m_fftwArguments.clear();
+ m_fftwArguments.append("-v");
+ m_fftwArguments.append("-n");
+ m_fftwArguments.append("-o");
+ m_fftwArguments.append(filePath);
+
+ for (int i = 7; i <= 7+fftMaxLog2; i++)
+ {
+ m_fftwArguments.append(QString("%1").arg(1<fftwCommand->setText(m_fftwExecPath + " " + argStr);
+}
diff --git a/sdrgui/gui/fftwisdomdialog.h b/sdrgui/gui/fftwisdomdialog.h
new file mode 100644
index 000000000..4a90f56f5
--- /dev/null
+++ b/sdrgui/gui/fftwisdomdialog.h
@@ -0,0 +1,57 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2021 F4EXB //
+// written by Edouard Griffiths //
+// //
+// 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 as version 3 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 V3 for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program. If not, see . //
+///////////////////////////////////////////////////////////////////////////////////
+
+#ifndef SDRGUI_GUI_FFTWISDOMDIALOG_H_
+#define SDRGUI_GUI_FFTWISDOMDIALOG_H_
+
+#include
+
+#include "export.h"
+
+namespace Ui {
+ class FFTWisdomDialog;
+}
+
+class QProcess;
+
+class SDRGUI_API FFTWisdomDialog : public QDialog {
+ Q_OBJECT
+public:
+ explicit FFTWisdomDialog(QProcess *process, QWidget* parent = nullptr);
+ ~FFTWisdomDialog();
+ QProcess *getProcess() { return m_process; }
+
+private slots:
+ void on_showFileDialog_clicked();
+ void on_fftwMaxSize_currentIndexChanged(int index);
+ void on_fftwReverse_toggled(bool checked);
+ void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
+ void accept();
+ void reject();
+
+private:
+ void updateArguments(int fftMaxLog2, bool includeReverse);
+
+ Ui::FFTWisdomDialog *ui;
+ QString m_fftwExecPath;
+ QStringList m_fftwArguments;
+ QProcess *m_process;
+};
+
+
+#endif // SDRGUI_GUI_FFTWISDOMDIALOG_H_
diff --git a/sdrgui/gui/fftwisdomdialog.ui b/sdrgui/gui/fftwisdomdialog.ui
new file mode 100644
index 000000000..e4b6dce2c
--- /dev/null
+++ b/sdrgui/gui/fftwisdomdialog.ui
@@ -0,0 +1,228 @@
+
+
+ FFTWisdomDialog
+
+
+
+ 0
+ 0
+ 427
+ 158
+
+
+
+
+ Liberation Sans
+ 9
+
+
+
+ FFTW Wisdom file generator
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Path to fftwf-wisdom executable
+
+
+ Program
+
+
+
+ -
+
+
+ Channel marker title
+
+
+
+ -
+
+
+
+ 24
+ 24
+
+
+
+
+ 24
+ 24
+
+
+
+ Open file
+
+
+
+
+
+
+ :/preset-load.png:/preset-load.png
+
+
+
+
+
+ -
+
+
-
+
+
+ FFT max
+
+
+
+ -
+
+
-
+
+ 128
+
+
+ -
+
+ 256
+
+
+ -
+
+ 512
+
+
+ -
+
+ 1k
+
+
+ -
+
+ 2k
+
+
+ -
+
+ 4k
+
+
+ -
+
+ 8k
+
+
+ -
+
+ 16k
+
+
+ -
+
+ 32k
+
+
+
+
+ -
+
+
+ Sychronize with reverse API
+
+
+ reverse FFT
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
-
+
+
+
+ 120
+ 0
+
+
+
+ FFTW Wisdom program invocation
+
+
+ ...
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ FFTWisdomDialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ FFTWisdomDialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/sdrgui/mainwindow.cpp b/sdrgui/mainwindow.cpp
index 0c90df667..a476a832a 100644
--- a/sdrgui/mainwindow.cpp
+++ b/sdrgui/mainwindow.cpp
@@ -57,6 +57,7 @@
#include "gui/deviceuserargsdialog.h"
#include "gui/sdrangelsplash.h"
#include "gui/mypositiondialog.h"
+#include "gui/fftwisdomdialog.h"
#include "gui/ambedevicesdialog.h"
#include "dsp/dspengine.h"
#include "dsp/spectrumvis.h"
@@ -101,7 +102,8 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse
m_inputGUI(0),
m_sampleRate(0),
m_centerFrequency(0),
- m_sampleFileName(std::string("./test.sdriq"))
+ m_sampleFileName(std::string("./test.sdriq")),
+ m_fftWisdomProcess(nullptr)
{
qDebug() << "MainWindow::MainWindow: start";
@@ -1778,6 +1780,48 @@ void MainWindow::on_action_DeviceUserArguments_triggered()
deviceUserArgsDialog.exec();
}
+void MainWindow::on_action_FFT_triggered()
+{
+ qDebug("MainWindow::on_action_FFT_triggered");
+ m_fftWisdomProcess = new QProcess(this);
+ connect(m_fftWisdomProcess,
+ SIGNAL(finished(int, QProcess::ExitStatus)),
+ this,
+ SLOT(fftWisdomProcessFinished(int, QProcess::ExitStatus)));
+ FFTWisdomDialog fftWisdomDialog(m_fftWisdomProcess, this);
+
+ if (fftWisdomDialog.exec() == QDialog::Rejected)
+ {
+ disconnect(m_fftWisdomProcess,
+ SIGNAL(finished(int, QProcess::ExitStatus)),
+ this,
+ SLOT(fftWisdomProcessFinished(int, QProcess::ExitStatus)));
+ delete m_fftWisdomProcess;
+ }
+ else
+ {
+ QMessageBox::information(this, "FFTW Wisdom", QString("Process %1 started").arg(m_fftWisdomProcess->processId()));
+ }
+}
+
+void MainWindow::fftWisdomProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
+{
+ qDebug("MainWindow::fftWisdomProcessFinished: process finished rc=%d (%d)", exitCode, (int) exitStatus);
+
+ if ((exitCode != 0) || (exitStatus != QProcess::NormalExit))
+ {
+ QMessageBox::critical(this, "FFTW Wisdom", "fftwf-widdsom program failed");
+ }
+ else
+ {
+ QString log = m_fftWisdomProcess->readAllStandardOutput();
+ QMessageBox::information(this, "FFTW Wisdom", QString("Success\n%1").arg(log));
+
+ }
+
+ delete m_fftWisdomProcess;
+}
+
void MainWindow::on_action_AMBE_triggered()
{
qDebug("MainWindow::on_action_AMBE_triggered");
diff --git a/sdrgui/mainwindow.h b/sdrgui/mainwindow.h
index 9a7e78323..127a60093 100644
--- a/sdrgui/mainwindow.h
+++ b/sdrgui/mainwindow.h
@@ -22,6 +22,7 @@
#include
#include
#include
+#include
#include "settings/mainsettings.h"
#include "util/message.h"
@@ -119,6 +120,8 @@ private:
CommandKeyReceiver *m_commandKeyReceiver;
+ QProcess *m_fftWisdomProcess;
+
void loadSettings();
void loadPresetSettings(const Preset* preset, int tabIndex);
void savePresetSettings(Preset* preset, int tabIndex);
@@ -173,6 +176,7 @@ private slots:
void on_commandKeyboardConnect_toggled(bool checked);
void on_action_Audio_triggered();
void on_action_Logging_triggered();
+ void on_action_FFT_triggered();
void on_action_AMBE_triggered();
void on_action_LimeRFE_triggered();
void on_action_My_Position_triggered();
@@ -192,6 +196,7 @@ private slots:
void tabChannelsIndexChanged();
void tabFeaturesIndexChanged();
void commandKeyPressed(Qt::Key key, Qt::KeyboardModifiers keyModifiers, bool release);
+ void fftWisdomProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
};
#endif // INCLUDE_MAINWINDOW_H
diff --git a/sdrgui/mainwindow.ui b/sdrgui/mainwindow.ui
index d48c3bffa..c6dba41aa 100644
--- a/sdrgui/mainwindow.ui
+++ b/sdrgui/mainwindow.ui
@@ -126,6 +126,7 @@
+
@@ -972,6 +973,11 @@
+
+
+ FFT
+
+
presetDock
channelDock
commandsDock