Fixed bug causing segfault when QAudioOutput was stopped

This commit is contained in:
Jordan Sherer 2019-10-08 21:26:17 -04:00
parent 9dc2c99ebd
commit 581d40010f
6 changed files with 64 additions and 29 deletions

View File

@ -1416,7 +1416,9 @@ Configuration::impl::impl (Configuration * self, QDir const& temp_directory,
table->setCellWidget(i, 3, w3);
i++;
}
table->resizeColumnsToContents();
table->resizeColumnToContents(0);
table->resizeColumnToContents(1);
table->resizeColumnToContents(2);
//

View File

@ -23,7 +23,7 @@
<string>Select tab to change configuration parameters.</string>
</property>
<property name="currentIndex">
<number>6</number>
<number>0</number>
</property>
<widget class="QWidget" name="general_tab">
<attribute name="title">
@ -278,7 +278,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>615</width>
<width>724</width>
<height>508</height>
</rect>
</property>
@ -793,8 +793,8 @@ text message.</string>
<rect>
<x>0</x>
<y>0</y>
<width>616</width>
<height>331</height>
<width>738</width>
<height>453</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_16">
@ -2082,20 +2082,22 @@ both here.</string>
</sizepolicy>
</property>
<property name="toolTip">
<string>Select the audio CODEC to use for transmitting.
If this is your default device for system sounds then
<string>Select the audio CODEC to use for notifications.
If this is your default device for system sounds and transmission then
ensure that all system sounds are disabled otherwise
you will broadcast any systems sounds generated during
you will broadcast any systems sounds and notifications generated during
transmitting periods.</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QComboBox" name="notification_sound_output_channel_combo_box">
<property name="visible">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Select the audio channel used for transmission.
Unless you have multiple radios connected on different
channels; then you will usually want to select mono or
<string>Select the audio channel used for notifications.
You will usually want to select mono or
both here.</string>
</property>
<item>

View File

@ -4,8 +4,8 @@
NotificationAudio::NotificationAudio(QObject *parent) :
QIODevice(parent),
m_state(State::Stopped),
m_input(&m_data),
m_output(&m_data),
m_input(&m_data, this),
m_output(&m_data, this),
m_decoder(nullptr),
m_audio(nullptr)
{
@ -15,6 +15,16 @@ NotificationAudio::NotificationAudio(QObject *parent) :
m_isDecodingFinished = false;
}
NotificationAudio::~NotificationAudio(){
stop();
delete m_decoder;
m_decoder = nullptr;
delete m_audio;
m_audio = nullptr;
}
// initialize an audio device
void NotificationAudio::init(const QAudioDeviceInfo &device, const QAudioFormat& format) {
m_device = device;
@ -28,7 +38,7 @@ void NotificationAudio::init(const QAudioDeviceInfo &device, const QAudioFormat&
m_decoder->setAudioFormat(m_format);
if(!m_audio){
m_audio = new QAudioOutput(m_device, m_format);
m_audio = new QAudioOutput(m_device, m_format, this);
}
if (!m_output.open(QIODevice::ReadOnly) || !m_input.open(QIODevice::WriteOnly)){
@ -42,6 +52,10 @@ void NotificationAudio::init(const QAudioDeviceInfo &device, const QAudioFormat&
// play an audio file
void NotificationAudio::play(const QString &filePath) {
if(m_state == NotificationAudio::Playing){
return;
}
QFile *file = new QFile(this);
file->setFileName(filePath);
if (!file->open(QIODevice::ReadOnly)){
@ -78,8 +92,9 @@ void NotificationAudio::stop() {
// Reset the internal buffers and ensure the decoder and audio device is stopped
void NotificationAudio::resetBuffers() {
if(m_audio){
if(m_audio->state() != QAudio::StoppedState){
m_audio->stop();
if(m_audio->state() != QAudio::SuspendedState){
m_audio->suspend();
}
}
@ -105,21 +120,18 @@ void NotificationAudio::resetBuffers() {
qint64 NotificationAudio::readData(char* data, qint64 maxlen) {
memset(data, 0, maxlen);
if (m_state == State::Playing)
{
if (m_state == State::Playing){
m_output.read(data, maxlen);
// There is we send readed audio data via signal, for ability get audio signal for the who listen this signal.
// Other word this emulate QAudioProbe behaviour for retrieve audio data which of sent to output device (speaker).
if (maxlen > 0)
{
QByteArray buff(data, maxlen);
emit newData(buff);
}
// if (maxlen > 0){
// QByteArray buff(data, maxlen);
// emit newData(buff);
// }
// Is finish of file
if (atEnd())
{
if (atEnd()){
stop();
}
}
@ -137,9 +149,10 @@ qint64 NotificationAudio::writeData(const char* data, qint64 len) {
// io device, at end of device
bool NotificationAudio::atEnd() const {
return m_output.size()
bool value = m_output.size()
&& m_output.atEnd()
&& m_isDecodingFinished;
return value;
}
// handle buffered data ready

View File

@ -18,6 +18,7 @@ class NotificationAudio : public QIODevice
public:
NotificationAudio(QObject * parent=nullptr);
~NotificationAudio();
bool isInitialized() const { return m_init; }

View File

@ -439,6 +439,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
m_framesAudioInputBuffered (RX_SAMPLE_RATE / 10),
m_downSampleFactor (downSampleFactor),
m_audioThreadPriority (QThread::HighPriority),
m_notificationAudioThreadPriority (QThread::LowPriority),
m_bandEdited {false},
m_splitMode {false},
m_monitoring {false},
@ -503,12 +504,13 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
m_modulator->moveToThread (&m_audioThread);
m_soundInput->moveToThread (&m_audioThread);
m_detector->moveToThread (&m_audioThread);
m_notification->moveToThread(&m_audioThread);
// notification audio operates in its own thread at a lower priority
m_notification->moveToThread(&m_notificationAudioThread);
// 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);
@ -517,7 +519,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
emit playNotification("/tmp/test.wav");
});
connect(this, &MainWindow::playNotification, m_notification, &NotificationAudio::play);
connect (&m_audioThread, &QThread::finished, m_notification, &QObject::deleteLater);
connect (&m_notificationAudioThread, &QThread::finished, m_notification, &QObject::deleteLater);
// hook up Modulator slots and disposal
connect (this, &MainWindow::transmitFrequency, m_modulator, &Modulator::setFrequency);
@ -841,6 +843,10 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
connect(m_wideGraph.data(), &WideGraph::qsy, this, &MainWindow::qsy);
connect(ui->tableWidgetCalls, &QTableWidget::clicked, this, [this](){
emit playNotification("/tmp/test.wav");
});
decodeBusy(false);
QString t1[28]={"1 uW","2 uW","5 uW","10 uW","20 uW","50 uW","100 uW","200 uW","500 uW",
"1 mW","2 mW","5 mW","10 mW","20 mW","50 mW","100 mW","200 mW","500 mW",
@ -870,7 +876,9 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
displayDialFrequency();
readSettings(); //Restore user's setup params
m_audioThread.start (m_audioThreadPriority);
m_notificationAudioThread.start(m_notificationAudioThreadPriority);
#ifdef WIN32
if (!m_multiple)
@ -943,6 +951,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
// 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 initializeNotificationAudioOutputStream(m_config.notification_audio_output_device(), m_config.notification_audio_output_device().preferredFormat());
Q_EMIT transmitFrequency (ui->TxFreqSpinBox->value () - m_XIT);
enable_DXCC_entity (m_config.DXCC ()); // sets text window proportions and (re)inits the logbook
@ -2141,9 +2150,15 @@ MainWindow::~MainWindow()
m_astroWidget.reset ();
QString fname {QDir::toNativeSeparators(m_config.writeable_data_dir ().absoluteFilePath ("wsjtx_wisdom.dat"))};
QByteArray cfname=fname.toLocal8Bit();
fftwf_export_wisdom_to_filename(cfname);
m_audioThread.quit ();
m_audioThread.wait ();
m_notificationAudioThread.quit();
m_notificationAudioThread.wait();
remove_child_from_event_filter (this);
}

View File

@ -507,6 +507,7 @@ private:
SoundOutput * m_soundOutput;
NotificationAudio * m_notification;
QThread m_audioThread;
QThread m_notificationAudioThread;
qint64 m_msErase;
qint64 m_secBandChanged;
@ -906,6 +907,7 @@ private:
unsigned m_framesAudioInputBuffered;
unsigned m_downSampleFactor;
QThread::Priority m_audioThreadPriority;
QThread::Priority m_notificationAudioThreadPriority;
bool m_bandEdited;
bool m_splitMode;
bool m_monitoring;