mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-21 11:31:51 -05:00
Start dealing with thread related object lifetime issues
There are several object lifetime issues that can cause crashes on application close down. This change is the first phase of addressing these issues. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@5719 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
parent
310481bcaa
commit
76eed0ecc4
@ -4,6 +4,7 @@
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include "mainwindow.h"
|
||||
#include "soundout.h"
|
||||
|
||||
#include "moc_Modulator.cpp"
|
||||
|
||||
@ -27,7 +28,6 @@ unsigned const Modulator::m_nspd = 2048 + 512; // 22.5 WPM
|
||||
Modulator::Modulator (unsigned frameRate, unsigned periodLengthInSeconds,
|
||||
QObject * parent)
|
||||
: AudioDevice {parent}
|
||||
, m_stream {nullptr}
|
||||
, m_quickClose {false}
|
||||
, m_phi {0.0}
|
||||
, m_toneSpacing {0.0}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define MODULATOR_HPP__
|
||||
|
||||
#include <QAudio>
|
||||
#include <QPointer>
|
||||
|
||||
#include "AudioDevice.hpp"
|
||||
|
||||
@ -48,7 +49,7 @@ protected:
|
||||
private:
|
||||
qint16 postProcessSample (qint16 sample) const;
|
||||
|
||||
SoundOutput * m_stream;
|
||||
QPointer<SoundOutput> m_stream;
|
||||
bool m_quickClose;
|
||||
|
||||
unsigned m_symbolsLength;
|
||||
|
120
mainwindow.cpp
120
mainwindow.cpp
@ -4,7 +4,6 @@
|
||||
#include <cinttypes>
|
||||
#include <limits>
|
||||
|
||||
#include <QThread>
|
||||
#include <QLineEdit>
|
||||
#include <QRegExpValidator>
|
||||
#include <QRegExp>
|
||||
@ -21,6 +20,9 @@
|
||||
#include "revision_utils.hpp"
|
||||
#include "qt_helpers.hpp"
|
||||
#include "soundout.h"
|
||||
#include "soundin.h"
|
||||
#include "Modulator.hpp"
|
||||
#include "Detector.hpp"
|
||||
#include "plotter.h"
|
||||
#include "echoplot.h"
|
||||
#include "echograph.h"
|
||||
@ -83,9 +85,10 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
|
||||
m_echoGraph (new EchoGraph(settings)),
|
||||
m_logDlg (new LogQSO (program_title (), settings, this)),
|
||||
m_dialFreq {std::numeric_limits<Radio::Frequency>::max ()},
|
||||
m_detector (RX_SAMPLE_RATE, NTMAX, 6912 / 2, downSampleFactor),
|
||||
m_modulator (TX_SAMPLE_RATE, NTMAX),
|
||||
m_audioThread {new QThread},
|
||||
m_detector {new Detector {RX_SAMPLE_RATE, NTMAX, 6912 / 2, downSampleFactor}},
|
||||
m_soundInput {new SoundInput},
|
||||
m_modulator {new Modulator {TX_SAMPLE_RATE, NTMAX}},
|
||||
m_soundOutput {new SoundOutput},
|
||||
m_XIT {0},
|
||||
m_pctx {0},
|
||||
m_diskData {false},
|
||||
@ -133,39 +136,39 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
|
||||
// start audio thread and hook up slots & signals for shutdown management
|
||||
// these objects need to be in the audio thread so that invoking
|
||||
// their slots is done in a thread safe way
|
||||
m_soundOutput.moveToThread (m_audioThread);
|
||||
m_modulator.moveToThread (m_audioThread);
|
||||
m_soundInput.moveToThread (m_audioThread);
|
||||
m_detector.moveToThread (m_audioThread);
|
||||
m_soundOutput->moveToThread (&m_audioThread);
|
||||
m_modulator->moveToThread (&m_audioThread);
|
||||
m_soundInput->moveToThread (&m_audioThread);
|
||||
m_detector->moveToThread (&m_audioThread);
|
||||
|
||||
connect (this, &MainWindow::finished, m_audioThread, &QThread::quit); // quit thread event loop
|
||||
connect (m_audioThread, &QThread::finished, m_audioThread, &QThread::deleteLater); // disposal
|
||||
// hook up sound output stream slots & signals and disposal
|
||||
connect (this, &MainWindow::initializeAudioOutputStream, m_soundOutput, &SoundOutput::setFormat);
|
||||
connect (m_soundOutput, &SoundOutput::error, this, &MainWindow::showSoundOutError);
|
||||
// connect (m_soundOutput, &SoundOutput::status, this, &MainWindow::showStatusMessage);
|
||||
connect (this, &MainWindow::outAttenuationChanged, m_soundOutput, &SoundOutput::setAttenuation);
|
||||
connect (&m_audioThread, &QThread::finished, m_soundOutput, &QObject::deleteLater);
|
||||
|
||||
// hook up sound output stream slots & signals
|
||||
connect (this, &MainWindow::initializeAudioOutputStream, &m_soundOutput, &SoundOutput::setFormat);
|
||||
connect (&m_soundOutput, &SoundOutput::error, this, &MainWindow::showSoundOutError);
|
||||
// connect (&m_soundOutput, &SoundOutput::status, this, &MainWindow::showStatusMessage);
|
||||
connect (this, &MainWindow::outAttenuationChanged, &m_soundOutput, &SoundOutput::setAttenuation);
|
||||
// hook up Modulator slots and disposal
|
||||
connect (this, &MainWindow::transmitFrequency, m_modulator, &Modulator::setFrequency);
|
||||
connect (this, &MainWindow::endTransmitMessage, m_modulator, &Modulator::stop);
|
||||
connect (this, &MainWindow::tune, m_modulator, &Modulator::tune);
|
||||
connect (this, &MainWindow::sendMessage, m_modulator, &Modulator::start);
|
||||
connect (&m_audioThread, &QThread::finished, m_modulator, &QObject::deleteLater);
|
||||
|
||||
// hook up Modulator slots
|
||||
connect (this, &MainWindow::transmitFrequency, &m_modulator, &Modulator::setFrequency);
|
||||
connect (this, &MainWindow::endTransmitMessage, &m_modulator, &Modulator::stop);
|
||||
connect (this, &MainWindow::tune, &m_modulator, &Modulator::tune);
|
||||
connect (this, &MainWindow::sendMessage, &m_modulator, &Modulator::start);
|
||||
|
||||
// hook up the audio input stream
|
||||
connect (this, &MainWindow::startAudioInputStream, &m_soundInput, &SoundInput::start);
|
||||
connect (this, &MainWindow::suspendAudioInputStream, &m_soundInput, &SoundInput::suspend);
|
||||
connect (this, &MainWindow::resumeAudioInputStream, &m_soundInput, &SoundInput::resume);
|
||||
connect (this, &MainWindow::finished, &m_soundInput, &SoundInput::stop);
|
||||
// hook up the audio input stream signals, slots and disposal
|
||||
connect (this, &MainWindow::startAudioInputStream, m_soundInput, &SoundInput::start);
|
||||
connect (this, &MainWindow::suspendAudioInputStream, m_soundInput, &SoundInput::suspend);
|
||||
connect (this, &MainWindow::resumeAudioInputStream, m_soundInput, &SoundInput::resume);
|
||||
connect (this, &MainWindow::finished, m_soundInput, &SoundInput::stop);
|
||||
connect(m_soundInput, &SoundInput::error, this, &MainWindow::showSoundInError);
|
||||
// connect(m_soundInput, &SoundInput::status, this, &MainWindow::showStatusMessage);
|
||||
connect (&m_audioThread, &QThread::finished, m_soundInput, &QObject::deleteLater);
|
||||
|
||||
connect (this, &MainWindow::finished, this, &MainWindow::close);
|
||||
|
||||
connect(&m_soundInput, &SoundInput::error, this, &MainWindow::showSoundInError);
|
||||
// connect(&m_soundInput, &SoundInput::status, this, &MainWindow::showStatusMessage);
|
||||
|
||||
// hook up the detector
|
||||
connect(&m_detector, &Detector::framesWritten, this, &MainWindow::dataSink);
|
||||
// hook up the detector signals, slots and disposal
|
||||
connect(m_detector, &Detector::framesWritten, this, &MainWindow::dataSink);
|
||||
connect (&m_audioThread, &QThread::finished, m_detector, &QObject::deleteLater);
|
||||
|
||||
// setup the waterfall
|
||||
connect(m_wideGraph.data (), SIGNAL(freezeDecode2(int)),this,
|
||||
@ -428,7 +431,7 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
|
||||
|
||||
readSettings(); //Restore user's setup params
|
||||
// start the audio thread
|
||||
m_audioThread->start (m_audioThreadPriority);
|
||||
m_audioThread.start (m_audioThreadPriority);
|
||||
|
||||
#ifdef WIN32
|
||||
if (!m_multiple)
|
||||
@ -523,7 +526,7 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
|
||||
watcher2 = new QFutureWatcher<void>;
|
||||
connect(watcher2, SIGNAL(finished()),this,SLOT(diskWriteFinished()));
|
||||
|
||||
Q_EMIT startAudioInputStream (m_config.audio_input_device (), m_framesAudioInputBuffered, &m_detector, m_downSampleFactor, m_config.audio_input_channel ());
|
||||
Q_EMIT startAudioInputStream (m_config.audio_input_device (), m_framesAudioInputBuffered, m_detector, m_downSampleFactor, m_config.audio_input_channel ());
|
||||
Q_EMIT initializeAudioOutputStream (m_config.audio_output_device (), AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2, m_msAudioOutputBuffered);
|
||||
Q_EMIT transmitFrequency (ui->TxFreqSpinBox->value () - m_XIT);
|
||||
|
||||
@ -557,7 +560,7 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
|
||||
m_hsymStop=173;
|
||||
if(m_config.decode_at_52s()) m_hsymStop=181;
|
||||
}
|
||||
m_modulator.setPeriod(m_TRperiod);
|
||||
m_modulator->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_dialFreqRxWSPR=0;
|
||||
wsprNet = new WSPRNet(this);
|
||||
connect( wsprNet, SIGNAL(uploadStatus(QString)), this, SLOT(uploadResponse(QString)));
|
||||
@ -574,7 +577,8 @@ MainWindow::~MainWindow()
|
||||
QString fname {QDir::toNativeSeparators(m_dataDir.absoluteFilePath ("wsjtx_wisdom.dat"))};
|
||||
QByteArray cfname=fname.toLocal8Bit();
|
||||
fftwf_export_wisdom_to_filename(cfname);
|
||||
m_audioThread->wait ();
|
||||
m_audioThread.quit ();
|
||||
m_audioThread.wait ();
|
||||
delete ui, ui = 0;
|
||||
}
|
||||
|
||||
@ -898,7 +902,7 @@ void MainWindow::on_actionSettings_triggered() //Setup Dialog
|
||||
if(m_mode=="JT9W-1") m_toneSpacing=pow(2,m_config.jt9w_bw_mult ())*12000.0/6912.0;
|
||||
|
||||
if(m_config.restart_audio_input ()) {
|
||||
Q_EMIT startAudioInputStream (m_config.audio_input_device (), m_framesAudioInputBuffered, &m_detector, m_downSampleFactor, m_config.audio_input_channel ());
|
||||
Q_EMIT startAudioInputStream (m_config.audio_input_device (), m_framesAudioInputBuffered, m_detector, m_downSampleFactor, m_config.audio_input_channel ());
|
||||
}
|
||||
if(m_config.restart_audio_output ()) {
|
||||
Q_EMIT initializeAudioOutputStream (m_config.audio_output_device (), AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2, m_msAudioOutputBuffered);
|
||||
@ -2124,12 +2128,12 @@ void MainWindow::guiUpdate()
|
||||
|
||||
void MainWindow::startTx2()
|
||||
{
|
||||
if (!m_modulator.isActive ()) {
|
||||
if (!m_modulator->isActive ()) { // TODO - not thread safe
|
||||
double fSpread=0.0;
|
||||
double snr=99.0;
|
||||
QString t=ui->tx5->currentText();
|
||||
if(t.mid(0,1)=="#") fSpread=t.mid(1,5).toDouble();
|
||||
m_modulator.setSpread(fSpread);
|
||||
m_modulator->setSpread(fSpread); // TODO - not thread safe
|
||||
t=ui->tx6->text();
|
||||
if(t.mid(0,1)=="#") snr=t.mid(1,5).toDouble();
|
||||
if(snr>0.0 or snr < -50.0) snr=99.0;
|
||||
@ -2818,7 +2822,7 @@ void MainWindow::on_tx6_editingFinished() //tx6 edited
|
||||
|
||||
// double snr=t.mid(1,5).toDouble();
|
||||
// if(snr>0.0 or snr < -50.0) snr=99.0;
|
||||
// m_modulator.setTxSNR(snr);
|
||||
// m_modulator->setTxSNR(snr); // TODO - not thread safe
|
||||
}
|
||||
|
||||
void MainWindow::on_dxCallEntry_textChanged(const QString &t) //dxCall changed
|
||||
@ -2907,8 +2911,8 @@ void MainWindow::on_actionJT9_1_triggered()
|
||||
if(m_modeTx!="JT9") on_pbTxMode_clicked();
|
||||
statusChanged();
|
||||
m_TRperiod=60;
|
||||
m_modulator.setPeriod(m_TRperiod);
|
||||
m_detector.setPeriod(m_TRperiod);
|
||||
m_modulator->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_detector->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_nsps=6912;
|
||||
m_hsymStop=173;
|
||||
if(m_config.decode_at_52s()) m_hsymStop=181;
|
||||
@ -2935,8 +2939,8 @@ void MainWindow::on_actionJT9W_1_triggered()
|
||||
if(m_modeTx!="JT9") on_pbTxMode_clicked();
|
||||
statusChanged();
|
||||
m_TRperiod=60;
|
||||
m_modulator.setPeriod(m_TRperiod);
|
||||
m_detector.setPeriod(m_TRperiod);
|
||||
m_modulator->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_detector->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_nsps=6912;
|
||||
m_hsymStop=173;
|
||||
if(m_config.decode_at_52s()) m_hsymStop=181;
|
||||
@ -2969,8 +2973,8 @@ void MainWindow::on_actionJT65_triggered()
|
||||
if(m_modeTx!="JT65") on_pbTxMode_clicked();
|
||||
statusChanged();
|
||||
m_TRperiod=60;
|
||||
m_modulator.setPeriod(m_TRperiod);
|
||||
m_detector.setPeriod(m_TRperiod);
|
||||
m_modulator->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_detector->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_nsps=6912; //For symspec only
|
||||
m_hsymStop=173;
|
||||
if(m_config.decode_at_52s()) m_hsymStop=181;
|
||||
@ -3008,8 +3012,8 @@ void MainWindow::on_actionJT9_JT65_triggered()
|
||||
m_nSubMode=0; //Dual-mode always means JT9 and JT65A
|
||||
statusChanged();
|
||||
m_TRperiod=60;
|
||||
m_modulator.setPeriod(m_TRperiod);
|
||||
m_detector.setPeriod(m_TRperiod);
|
||||
m_modulator->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_detector->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_nsps=6912;
|
||||
m_hsymStop=173;
|
||||
if(m_config.decode_at_52s()) m_hsymStop=181;
|
||||
@ -3036,8 +3040,8 @@ void MainWindow::on_actionJT4_triggered()
|
||||
m_modeTx="JT4";
|
||||
statusChanged();
|
||||
m_TRperiod=60;
|
||||
m_modulator.setPeriod(m_TRperiod);
|
||||
m_detector.setPeriod(m_TRperiod);
|
||||
m_modulator->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_detector->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_nsps=6912; //For symspec only
|
||||
m_hsymStop=181;
|
||||
// if(m_config.decode_at_52s()) m_hsymStop=181;
|
||||
@ -3075,8 +3079,8 @@ void MainWindow::on_actionWSPR_2_triggered()
|
||||
m_modeTx="WSPR-2"; //### not needed ?? ###
|
||||
statusChanged();
|
||||
m_TRperiod=120;
|
||||
m_modulator.setPeriod(m_TRperiod);
|
||||
m_detector.setPeriod(m_TRperiod);
|
||||
m_modulator->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_detector->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_nsps=6912; //For symspec only
|
||||
m_hsymStop=396;
|
||||
m_toneSpacing=12000.0/8192.0;
|
||||
@ -3103,8 +3107,8 @@ void MainWindow::on_actionEcho_triggered()
|
||||
m_mode="Echo";
|
||||
ui->actionEcho->setChecked(true);
|
||||
m_TRperiod=3;
|
||||
m_modulator.setPeriod(m_TRperiod);
|
||||
m_detector.setPeriod(m_TRperiod);
|
||||
m_modulator->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_detector->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_nsps=6912; //For symspec only
|
||||
m_hsymStop=10;
|
||||
m_toneSpacing=1.0;
|
||||
@ -3618,13 +3622,13 @@ void MainWindow::transmit (double snr)
|
||||
if(m_nSubMode==2) toneSpacing=4*11025.0/4096.0;
|
||||
Q_EMIT sendMessage (NUM_JT65_SYMBOLS,
|
||||
4096.0*12000.0/11025.0, ui->TxFreqSpinBox->value () - m_XIT,
|
||||
toneSpacing, &m_soundOutput, m_config.audio_output_channel (),
|
||||
toneSpacing, m_soundOutput, m_config.audio_output_channel (),
|
||||
true, snr);
|
||||
}
|
||||
if (m_modeTx == "JT9") {
|
||||
Q_EMIT sendMessage (NUM_JT9_SYMBOLS, m_nsps,
|
||||
ui->TxFreqSpinBox->value () - m_XIT, m_toneSpacing,
|
||||
&m_soundOutput, m_config.audio_output_channel (), true, snr);
|
||||
m_soundOutput, m_config.audio_output_channel (), true, snr);
|
||||
}
|
||||
if (m_modeTx == "JT4") {
|
||||
if(m_nSubMode==0) toneSpacing=4.375;
|
||||
@ -3636,18 +3640,18 @@ void MainWindow::transmit (double snr)
|
||||
if(m_nSubMode==6) toneSpacing=72*4.375;
|
||||
Q_EMIT sendMessage (NUM_JT4_SYMBOLS,
|
||||
2520.0*12000.0/11025.0, ui->TxFreqSpinBox->value () - m_XIT,
|
||||
toneSpacing, &m_soundOutput, m_config.audio_output_channel (),
|
||||
toneSpacing, m_soundOutput, m_config.audio_output_channel (),
|
||||
true, snr);
|
||||
}
|
||||
if (m_mode=="WSPR-2") { //### Similar code needed for WSPR-15 ###
|
||||
|
||||
Q_EMIT sendMessage (NUM_WSPR_SYMBOLS, 8192.0,
|
||||
ui->TxFreqSpinBox->value() - 1.5 * 12000 / 8192, m_toneSpacing,
|
||||
&m_soundOutput, m_config.audio_output_channel(),
|
||||
m_soundOutput, m_config.audio_output_channel(),
|
||||
true, snr);
|
||||
}
|
||||
if(m_mode=="Echo") {
|
||||
Q_EMIT sendMessage (27, 1024.0, 1500.0, 0.0, &m_soundOutput,
|
||||
Q_EMIT sendMessage (27, 1024.0, 1500.0, 0.0, m_soundOutput,
|
||||
m_config.audio_output_channel(),false, snr);
|
||||
}
|
||||
}
|
||||
|
18
mainwindow.h
18
mainwindow.h
@ -18,9 +18,7 @@
|
||||
#include <QHostAddress>
|
||||
#include <QPointer>
|
||||
|
||||
#include "soundin.h"
|
||||
#include "AudioDevice.hpp"
|
||||
#include "soundout.h"
|
||||
#include "commons.h"
|
||||
#include "Radio.hpp"
|
||||
#include "Modes.hpp"
|
||||
@ -29,8 +27,6 @@
|
||||
#include "Transceiver.hpp"
|
||||
#include "psk_reporter.h"
|
||||
#include "logbook/logbook.h"
|
||||
#include "Detector.hpp"
|
||||
#include "Modulator.hpp"
|
||||
#include "decodedtext.h"
|
||||
|
||||
#define NUM_JT4_SYMBOLS 206
|
||||
@ -63,6 +59,10 @@ class QTime;
|
||||
class WSPRBandHopping;
|
||||
class HelpTextWindow;
|
||||
class WSPRNet;
|
||||
class SoundOutput;
|
||||
class Modulator;
|
||||
class SoundInput;
|
||||
class Detector;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
@ -282,11 +282,11 @@ private:
|
||||
Frequency m_dialFreq;
|
||||
Frequency m_dialFreqRxWSPR;
|
||||
|
||||
Detector m_detector;
|
||||
SoundInput m_soundInput;
|
||||
Modulator m_modulator;
|
||||
SoundOutput m_soundOutput;
|
||||
QThread * m_audioThread;
|
||||
Detector * m_detector;
|
||||
SoundInput * m_soundInput;
|
||||
Modulator * m_modulator;
|
||||
SoundOutput * m_soundOutput;
|
||||
QThread m_audioThread;
|
||||
|
||||
qint64 m_msErase;
|
||||
qint64 m_secBandChanged;
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <QString>
|
||||
#include <QDateTime>
|
||||
#include <QScopedPointer>
|
||||
#include <QPointer>
|
||||
#include <QAudioInput>
|
||||
|
||||
#include "AudioDevice.hpp"
|
||||
@ -45,7 +46,7 @@ private:
|
||||
bool audioError () const;
|
||||
|
||||
QScopedPointer<QAudioInput> m_stream;
|
||||
AudioDevice * m_sink;
|
||||
QPointer<AudioDevice> m_sink;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user