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);
|
||||
i++;
|
||||
}
|
||||
table->resizeColumnsToContents();
|
||||
table->resizeColumnToContents(0);
|
||||
table->resizeColumnToContents(1);
|
||||
table->resizeColumnToContents(2);
|
||||
|
||||
|
||||
//
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -18,6 +18,7 @@ class NotificationAudio : public QIODevice
|
||||
|
||||
public:
|
||||
NotificationAudio(QObject * parent=nullptr);
|
||||
~NotificationAudio();
|
||||
|
||||
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_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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user