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