Fixed bug causing segfault when QAudioOutput was stopped
This commit is contained in:
parent
9dc2c99ebd
commit
581d40010f
@ -1416,7 +1416,9 @@ Configuration::impl::impl (Configuration * self, QDir const& temp_directory,
|
|||||||
table->setCellWidget(i, 3, w3);
|
table->setCellWidget(i, 3, w3);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
table->resizeColumnsToContents();
|
table->resizeColumnToContents(0);
|
||||||
|
table->resizeColumnToContents(1);
|
||||||
|
table->resizeColumnToContents(2);
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
<string>Select tab to change configuration parameters.</string>
|
<string>Select tab to change configuration parameters.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>6</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="general_tab">
|
<widget class="QWidget" name="general_tab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
@ -278,7 +278,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>615</width>
|
<width>724</width>
|
||||||
<height>508</height>
|
<height>508</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -793,8 +793,8 @@ text message.</string>
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>616</width>
|
<width>738</width>
|
||||||
<height>331</height>
|
<height>453</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||||
@ -2082,20 +2082,22 @@ both here.</string>
|
|||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Select the audio CODEC to use for transmitting.
|
<string>Select the audio CODEC to use for notifications.
|
||||||
If this is your default device for system sounds then
|
If this is your default device for system sounds and transmission then
|
||||||
ensure that all system sounds are disabled otherwise
|
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>
|
transmitting periods.</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2">
|
<item row="0" column="2">
|
||||||
<widget class="QComboBox" name="notification_sound_output_channel_combo_box">
|
<widget class="QComboBox" name="notification_sound_output_channel_combo_box">
|
||||||
|
<property name="visible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Select the audio channel used for transmission.
|
<string>Select the audio channel used for notifications.
|
||||||
Unless you have multiple radios connected on different
|
You will usually want to select mono or
|
||||||
channels; then you will usually want to select mono or
|
|
||||||
both here.</string>
|
both here.</string>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
NotificationAudio::NotificationAudio(QObject *parent) :
|
NotificationAudio::NotificationAudio(QObject *parent) :
|
||||||
QIODevice(parent),
|
QIODevice(parent),
|
||||||
m_state(State::Stopped),
|
m_state(State::Stopped),
|
||||||
m_input(&m_data),
|
m_input(&m_data, this),
|
||||||
m_output(&m_data),
|
m_output(&m_data, this),
|
||||||
m_decoder(nullptr),
|
m_decoder(nullptr),
|
||||||
m_audio(nullptr)
|
m_audio(nullptr)
|
||||||
{
|
{
|
||||||
@ -15,6 +15,16 @@ NotificationAudio::NotificationAudio(QObject *parent) :
|
|||||||
m_isDecodingFinished = false;
|
m_isDecodingFinished = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NotificationAudio::~NotificationAudio(){
|
||||||
|
stop();
|
||||||
|
|
||||||
|
delete m_decoder;
|
||||||
|
m_decoder = nullptr;
|
||||||
|
|
||||||
|
delete m_audio;
|
||||||
|
m_audio = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// initialize an audio device
|
// initialize an audio device
|
||||||
void NotificationAudio::init(const QAudioDeviceInfo &device, const QAudioFormat& format) {
|
void NotificationAudio::init(const QAudioDeviceInfo &device, const QAudioFormat& format) {
|
||||||
m_device = device;
|
m_device = device;
|
||||||
@ -28,7 +38,7 @@ void NotificationAudio::init(const QAudioDeviceInfo &device, const QAudioFormat&
|
|||||||
m_decoder->setAudioFormat(m_format);
|
m_decoder->setAudioFormat(m_format);
|
||||||
|
|
||||||
if(!m_audio){
|
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)){
|
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
|
// play an audio file
|
||||||
void NotificationAudio::play(const QString &filePath) {
|
void NotificationAudio::play(const QString &filePath) {
|
||||||
|
if(m_state == NotificationAudio::Playing){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QFile *file = new QFile(this);
|
QFile *file = new QFile(this);
|
||||||
file->setFileName(filePath);
|
file->setFileName(filePath);
|
||||||
if (!file->open(QIODevice::ReadOnly)){
|
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
|
// Reset the internal buffers and ensure the decoder and audio device is stopped
|
||||||
void NotificationAudio::resetBuffers() {
|
void NotificationAudio::resetBuffers() {
|
||||||
if(m_audio){
|
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) {
|
qint64 NotificationAudio::readData(char* data, qint64 maxlen) {
|
||||||
memset(data, 0, maxlen);
|
memset(data, 0, maxlen);
|
||||||
|
|
||||||
if (m_state == State::Playing)
|
if (m_state == State::Playing){
|
||||||
{
|
|
||||||
m_output.read(data, maxlen);
|
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.
|
// 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).
|
// Other word this emulate QAudioProbe behaviour for retrieve audio data which of sent to output device (speaker).
|
||||||
if (maxlen > 0)
|
// if (maxlen > 0){
|
||||||
{
|
// QByteArray buff(data, maxlen);
|
||||||
QByteArray buff(data, maxlen);
|
// emit newData(buff);
|
||||||
emit newData(buff);
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
// Is finish of file
|
// Is finish of file
|
||||||
if (atEnd())
|
if (atEnd()){
|
||||||
{
|
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,9 +149,10 @@ qint64 NotificationAudio::writeData(const char* data, qint64 len) {
|
|||||||
|
|
||||||
// io device, at end of device
|
// io device, at end of device
|
||||||
bool NotificationAudio::atEnd() const {
|
bool NotificationAudio::atEnd() const {
|
||||||
return m_output.size()
|
bool value = m_output.size()
|
||||||
&& m_output.atEnd()
|
&& m_output.atEnd()
|
||||||
&& m_isDecodingFinished;
|
&& m_isDecodingFinished;
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle buffered data ready
|
// handle buffered data ready
|
||||||
|
@ -18,6 +18,7 @@ class NotificationAudio : public QIODevice
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
NotificationAudio(QObject * parent=nullptr);
|
NotificationAudio(QObject * parent=nullptr);
|
||||||
|
~NotificationAudio();
|
||||||
|
|
||||||
bool isInitialized() const { return m_init; }
|
bool isInitialized() const { return m_init; }
|
||||||
|
|
||||||
|
@ -439,6 +439,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
|||||||
m_framesAudioInputBuffered (RX_SAMPLE_RATE / 10),
|
m_framesAudioInputBuffered (RX_SAMPLE_RATE / 10),
|
||||||
m_downSampleFactor (downSampleFactor),
|
m_downSampleFactor (downSampleFactor),
|
||||||
m_audioThreadPriority (QThread::HighPriority),
|
m_audioThreadPriority (QThread::HighPriority),
|
||||||
|
m_notificationAudioThreadPriority (QThread::LowPriority),
|
||||||
m_bandEdited {false},
|
m_bandEdited {false},
|
||||||
m_splitMode {false},
|
m_splitMode {false},
|
||||||
m_monitoring {false},
|
m_monitoring {false},
|
||||||
@ -503,12 +504,13 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
|||||||
m_modulator->moveToThread (&m_audioThread);
|
m_modulator->moveToThread (&m_audioThread);
|
||||||
m_soundInput->moveToThread (&m_audioThread);
|
m_soundInput->moveToThread (&m_audioThread);
|
||||||
m_detector->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
|
// hook up sound output stream slots & signals and disposal
|
||||||
connect (this, &MainWindow::initializeAudioOutputStream, m_soundOutput, &SoundOutput::setFormat);
|
connect (this, &MainWindow::initializeAudioOutputStream, m_soundOutput, &SoundOutput::setFormat);
|
||||||
connect (m_soundOutput, &SoundOutput::error, this, &MainWindow::showSoundOutError);
|
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 (this, &MainWindow::outAttenuationChanged, m_soundOutput, &SoundOutput::setAttenuation);
|
||||||
connect (&m_audioThread, &QThread::finished, m_soundOutput, &QObject::deleteLater);
|
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");
|
emit playNotification("/tmp/test.wav");
|
||||||
});
|
});
|
||||||
connect(this, &MainWindow::playNotification, m_notification, &NotificationAudio::play);
|
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
|
// hook up Modulator slots and disposal
|
||||||
connect (this, &MainWindow::transmitFrequency, m_modulator, &Modulator::setFrequency);
|
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(m_wideGraph.data(), &WideGraph::qsy, this, &MainWindow::qsy);
|
||||||
|
|
||||||
|
connect(ui->tableWidgetCalls, &QTableWidget::clicked, this, [this](){
|
||||||
|
emit playNotification("/tmp/test.wav");
|
||||||
|
});
|
||||||
|
|
||||||
decodeBusy(false);
|
decodeBusy(false);
|
||||||
QString t1[28]={"1 uW","2 uW","5 uW","10 uW","20 uW","50 uW","100 uW","200 uW","500 uW",
|
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",
|
"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();
|
displayDialFrequency();
|
||||||
readSettings(); //Restore user's setup params
|
readSettings(); //Restore user's setup params
|
||||||
|
|
||||||
m_audioThread.start (m_audioThreadPriority);
|
m_audioThread.start (m_audioThreadPriority);
|
||||||
|
m_notificationAudioThread.start(m_notificationAudioThreadPriority);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
if (!m_multiple)
|
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 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 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);
|
Q_EMIT transmitFrequency (ui->TxFreqSpinBox->value () - m_XIT);
|
||||||
|
|
||||||
enable_DXCC_entity (m_config.DXCC ()); // sets text window proportions and (re)inits the logbook
|
enable_DXCC_entity (m_config.DXCC ()); // sets text window proportions and (re)inits the logbook
|
||||||
@ -2141,9 +2150,15 @@ MainWindow::~MainWindow()
|
|||||||
m_astroWidget.reset ();
|
m_astroWidget.reset ();
|
||||||
QString fname {QDir::toNativeSeparators(m_config.writeable_data_dir ().absoluteFilePath ("wsjtx_wisdom.dat"))};
|
QString fname {QDir::toNativeSeparators(m_config.writeable_data_dir ().absoluteFilePath ("wsjtx_wisdom.dat"))};
|
||||||
QByteArray cfname=fname.toLocal8Bit();
|
QByteArray cfname=fname.toLocal8Bit();
|
||||||
|
|
||||||
fftwf_export_wisdom_to_filename(cfname);
|
fftwf_export_wisdom_to_filename(cfname);
|
||||||
|
|
||||||
m_audioThread.quit ();
|
m_audioThread.quit ();
|
||||||
m_audioThread.wait ();
|
m_audioThread.wait ();
|
||||||
|
|
||||||
|
m_notificationAudioThread.quit();
|
||||||
|
m_notificationAudioThread.wait();
|
||||||
|
|
||||||
remove_child_from_event_filter (this);
|
remove_child_from_event_filter (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,6 +507,7 @@ private:
|
|||||||
SoundOutput * m_soundOutput;
|
SoundOutput * m_soundOutput;
|
||||||
NotificationAudio * m_notification;
|
NotificationAudio * m_notification;
|
||||||
QThread m_audioThread;
|
QThread m_audioThread;
|
||||||
|
QThread m_notificationAudioThread;
|
||||||
|
|
||||||
qint64 m_msErase;
|
qint64 m_msErase;
|
||||||
qint64 m_secBandChanged;
|
qint64 m_secBandChanged;
|
||||||
@ -906,6 +907,7 @@ private:
|
|||||||
unsigned m_framesAudioInputBuffered;
|
unsigned m_framesAudioInputBuffered;
|
||||||
unsigned m_downSampleFactor;
|
unsigned m_downSampleFactor;
|
||||||
QThread::Priority m_audioThreadPriority;
|
QThread::Priority m_audioThreadPriority;
|
||||||
|
QThread::Priority m_notificationAudioThreadPriority;
|
||||||
bool m_bandEdited;
|
bool m_bandEdited;
|
||||||
bool m_splitMode;
|
bool m_splitMode;
|
||||||
bool m_monitoring;
|
bool m_monitoring;
|
||||||
|
Loading…
Reference in New Issue
Block a user