diff options
author | Yoann Lopes <yoann.lopes@qt.io> | 2016-09-20 19:28:40 +0300 |
---|---|---|
committer | Yoann Lopes <yoann.lopes@qt.io> | 2016-09-21 13:13:05 +0000 |
commit | 4bae7697257e5294721211fdd0b9bad5731f70c9 (patch) | |
tree | e001043615ec95ff762fec7aaec8950a3df7770f /src | |
parent | bf5c7ca718a4a84e28a17ff69c4b18abee81ff93 (diff) | |
download | qtmultimedia-4bae7697257e5294721211fdd0b9bad5731f70c9.tar.gz |
PulseAudio: make code more robust
Some asynchronous operations return a pa_operation pointer, which can
be null if the operation fails. In some cases we were not checking that
the returned object was non null, leading to some asserts being raised
in pa_operation_unref.
Change-Id: Iff1cc67b7f79b758fa81d79e658debb1d737b29f
Reviewed-by: Christian Stromme <christian.stromme@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/multimedia/audio/qsoundeffect_pulse_p.cpp | 61 | ||||
-rw-r--r-- | src/plugins/pulseaudio/qpulseaudioengine.cpp | 65 |
2 files changed, 95 insertions, 31 deletions
diff --git a/src/multimedia/audio/qsoundeffect_pulse_p.cpp b/src/multimedia/audio/qsoundeffect_pulse_p.cpp index 1fb10d121..5bb5119a8 100644 --- a/src/multimedia/audio/qsoundeffect_pulse_p.cpp +++ b/src/multimedia/audio/qsoundeffect_pulse_p.cpp @@ -437,7 +437,11 @@ void QSoundEffectPrivate::setSource(const QUrl &url) if (m_pulseStream && !pa_stream_is_corked(m_pulseStream)) { pa_stream_set_write_callback(m_pulseStream, 0, 0); pa_stream_set_underflow_callback(m_pulseStream, 0, 0); - pa_operation_unref(pa_stream_cork(m_pulseStream, 1, 0, 0)); + pa_operation *op = pa_stream_cork(m_pulseStream, 1, 0, 0); + if (op) + pa_operation_unref(op); + else + qWarning("QSoundEffect(pulseaudio): failed to cork stream"); } setPlaying(false); @@ -619,7 +623,11 @@ void QSoundEffectPrivate::emptyStream(EmptyStreamOptions options) m_emptying = true; pa_stream_set_write_callback(m_pulseStream, 0, 0); pa_stream_set_underflow_callback(m_pulseStream, 0, 0); - pa_operation_unref(pa_stream_flush(m_pulseStream, flushCompleteCb, m_ref->getRef())); + pa_operation *op = pa_stream_flush(m_pulseStream, flushCompleteCb, m_ref->getRef()); + if (op) + pa_operation_unref(op); + else + qWarning("QSoundEffect(pulseaudio): failed to flush stream"); } void QSoundEffectPrivate::emptyComplete(void *stream, bool reload) @@ -631,8 +639,13 @@ void QSoundEffectPrivate::emptyComplete(void *stream, bool reload) m_emptying = false; - if ((pa_stream *)stream == m_pulseStream) - pa_operation_unref(pa_stream_cork(m_pulseStream, 1, reload ? stream_cork_callback : 0, m_ref->getRef())); + if ((pa_stream *)stream == m_pulseStream) { + pa_operation *op = pa_stream_cork(m_pulseStream, 1, reload ? stream_cork_callback : 0, m_ref->getRef()); + if (op) + pa_operation_unref(op); + else + qWarning("QSoundEffect(pulseaudio): failed to cork stream"); + } } void QSoundEffectPrivate::sampleReady() @@ -666,7 +679,11 @@ void QSoundEffectPrivate::sampleReady() pa_buffer_attr newBufferAttr; newBufferAttr = *bufferAttr; newBufferAttr.prebuf = m_sample->data().size(); - pa_operation_unref(pa_stream_set_buffer_attr(m_pulseStream, &newBufferAttr, stream_adjust_prebuffer_callback, m_ref->getRef())); + pa_operation *op = pa_stream_set_buffer_attr(m_pulseStream, &newBufferAttr, stream_adjust_prebuffer_callback, m_ref->getRef()); + if (op) + pa_operation_unref(op); + else + qWarning("QSoundEffect(pulseaudio): failed to adjust pre-buffer attribute"); } else { streamReady(); } @@ -679,12 +696,20 @@ void QSoundEffectPrivate::sampleReady() newBufferAttr.minreq = bufferAttr->tlength / 2; newBufferAttr.prebuf = -1; newBufferAttr.fragsize = -1; - pa_operation_unref(pa_stream_set_buffer_attr(m_pulseStream, &newBufferAttr, stream_reset_buffer_callback, m_ref->getRef())); + pa_operation *op = pa_stream_set_buffer_attr(m_pulseStream, &newBufferAttr, stream_reset_buffer_callback, m_ref->getRef()); + if (op) + pa_operation_unref(op); + else + qWarning("QSoundEffect(pulseaudio): failed to adjust pre-buffer attribute"); } else if (bufferAttr->prebuf > uint32_t(m_sample->data().size())) { pa_buffer_attr newBufferAttr; newBufferAttr = *bufferAttr; newBufferAttr.prebuf = m_sample->data().size(); - pa_operation_unref(pa_stream_set_buffer_attr(m_pulseStream, &newBufferAttr, stream_adjust_prebuffer_callback, m_ref->getRef())); + pa_operation *op = pa_stream_set_buffer_attr(m_pulseStream, &newBufferAttr, stream_adjust_prebuffer_callback, m_ref->getRef()); + if (op) + pa_operation_unref(op); + else + qWarning("QSoundEffect(pulseaudio): failed to adjust pre-buffer attribute"); } else { streamReady(); } @@ -989,7 +1014,11 @@ void QSoundEffectPrivate::stream_state_callback(pa_stream *s, void *userdata) pa_buffer_attr newBufferAttr; newBufferAttr = *bufferAttr; newBufferAttr.prebuf = self->m_sample->data().size(); - pa_stream_set_buffer_attr(self->m_pulseStream, &newBufferAttr, stream_adjust_prebuffer_callback, self->m_ref->getRef()); + pa_operation *op = pa_stream_set_buffer_attr(self->m_pulseStream, &newBufferAttr, stream_adjust_prebuffer_callback, self->m_ref->getRef()); + if (op) + pa_operation_unref(op); + else + qWarning("QSoundEffect(pulseaudio): failed to adjust pre-buffer attribute"); } else { QMetaObject::invokeMethod(self, "streamReady", Qt::QueuedConnection); } @@ -1026,7 +1055,7 @@ void QSoundEffectPrivate::stream_reset_buffer_callback(pa_stream *s, int success return; if (!success) - qWarning("QSoundEffect(pulseaudio): faild to reset buffer attribute"); + qWarning("QSoundEffect(pulseaudio): failed to reset buffer attribute"); #ifdef QT_PA_DEBUG qDebug() << self << "stream_reset_buffer_callback"; #endif @@ -1036,7 +1065,11 @@ void QSoundEffectPrivate::stream_reset_buffer_callback(pa_stream *s, int success pa_buffer_attr newBufferAttr; newBufferAttr = *bufferAttr; newBufferAttr.prebuf = self->m_sample->data().size(); - pa_stream_set_buffer_attr(self->m_pulseStream, &newBufferAttr, stream_adjust_prebuffer_callback, userdata); + pa_operation *op = pa_stream_set_buffer_attr(self->m_pulseStream, &newBufferAttr, stream_adjust_prebuffer_callback, userdata); + if (op) + pa_operation_unref(op); + else + qWarning("QSoundEffect(pulseaudio): failed to adjust pre-buffer attribute"); } else { QMetaObject::invokeMethod(self, "streamReady", Qt::QueuedConnection); } @@ -1055,7 +1088,7 @@ void QSoundEffectPrivate::stream_adjust_prebuffer_callback(pa_stream *s, int suc return; if (!success) - qWarning("QSoundEffect(pulseaudio): faild to adjust pre-buffer attribute"); + qWarning("QSoundEffect(pulseaudio): failed to adjust pre-buffer attribute"); #ifdef QT_PA_DEBUG qDebug() << self << "stream_adjust_prebuffer_callback"; #endif @@ -1090,7 +1123,7 @@ void QSoundEffectPrivate::stream_cork_callback(pa_stream *s, int success, void * return; if (!success) - qWarning("QSoundEffect(pulseaudio): faild to stop"); + qWarning("QSoundEffect(pulseaudio): failed to stop"); #ifdef QT_PA_DEBUG qDebug() << self << "stream_cork_callback"; #endif @@ -1110,7 +1143,7 @@ void QSoundEffectPrivate::stream_flush_callback(pa_stream *s, int success, void return; if (!success) - qWarning("QSoundEffect(pulseaudio): faild to drain"); + qWarning("QSoundEffect(pulseaudio): failed to drain"); QMetaObject::invokeMethod(self, "emptyComplete", Qt::QueuedConnection, Q_ARG(void*, s), Q_ARG(bool, false)); } @@ -1128,7 +1161,7 @@ void QSoundEffectPrivate::stream_flush_reload_callback(pa_stream *s, int success return; if (!success) - qWarning("QSoundEffect(pulseaudio): faild to drain"); + qWarning("QSoundEffect(pulseaudio): failed to drain"); QMetaObject::invokeMethod(self, "emptyComplete", Qt::QueuedConnection, Q_ARG(void*, s), Q_ARG(bool, true)); } diff --git a/src/plugins/pulseaudio/qpulseaudioengine.cpp b/src/plugins/pulseaudio/qpulseaudioengine.cpp index e9510fd6a..b3d5044b7 100644 --- a/src/plugins/pulseaudio/qpulseaudioengine.cpp +++ b/src/plugins/pulseaudio/qpulseaudioengine.cpp @@ -170,15 +170,30 @@ static void event_cb(pa_context* context, pa_subscription_event_type_t t, uint32 case PA_SUBSCRIPTION_EVENT_NEW: case PA_SUBSCRIPTION_EVENT_CHANGE: switch (facility) { - case PA_SUBSCRIPTION_EVENT_SERVER: - pa_operation_unref(pa_context_get_server_info(context, serverInfoCallback, userdata)); + case PA_SUBSCRIPTION_EVENT_SERVER: { + pa_operation *op = pa_context_get_server_info(context, serverInfoCallback, userdata); + if (op) + pa_operation_unref(op); + else + qWarning("PulseAudioService: failed to get server info"); break; - case PA_SUBSCRIPTION_EVENT_SINK: - pa_operation_unref(pa_context_get_sink_info_by_index(context, index, sinkInfoCallback, userdata)); + } + case PA_SUBSCRIPTION_EVENT_SINK: { + pa_operation *op = pa_context_get_sink_info_by_index(context, index, sinkInfoCallback, userdata); + if (op) + pa_operation_unref(op); + else + qWarning("PulseAudioService: failed to get sink info"); break; - case PA_SUBSCRIPTION_EVENT_SOURCE: - pa_operation_unref(pa_context_get_source_info_by_index(context, index, sourceInfoCallback, userdata)); + } + case PA_SUBSCRIPTION_EVENT_SOURCE: { + pa_operation *op = pa_context_get_source_info_by_index(context, index, sourceInfoCallback, userdata); + if (op) + pa_operation_unref(op); + else + qWarning("PulseAudioService: failed to get source info"); break; + } default: break; } @@ -328,11 +343,15 @@ void QPulseAudioEngine::prepare() pa_context_set_state_callback(m_context, contextStateCallback, this); pa_context_set_subscribe_callback(m_context, event_cb, this); - pa_operation_unref(pa_context_subscribe(m_context, + pa_operation *op = pa_context_subscribe(m_context, pa_subscription_mask_t(PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE | PA_SUBSCRIPTION_MASK_SERVER), - NULL, NULL)); + NULL, NULL); + if (op) + pa_operation_unref(op); + else + qWarning("PulseAudioService: failed to subscribe to context notifications"); } else { pa_context_unref(m_context); m_context = 0; @@ -376,21 +395,33 @@ void QPulseAudioEngine::updateDevices() // Get default input and output devices pa_operation *operation = pa_context_get_server_info(m_context, serverInfoCallback, this); - while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) - pa_threaded_mainloop_wait(m_mainLoop); - pa_operation_unref(operation); + if (operation) { + while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) + pa_threaded_mainloop_wait(m_mainLoop); + pa_operation_unref(operation); + } else { + qWarning("PulseAudioService: failed to get server info"); + } // Get output devices operation = pa_context_get_sink_info_list(m_context, sinkInfoCallback, this); - while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) - pa_threaded_mainloop_wait(m_mainLoop); - pa_operation_unref(operation); + if (operation) { + while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) + pa_threaded_mainloop_wait(m_mainLoop); + pa_operation_unref(operation); + } else { + qWarning("PulseAudioService: failed to get sink info"); + } // Get input devices operation = pa_context_get_source_info_list(m_context, sourceInfoCallback, this); - while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) - pa_threaded_mainloop_wait(m_mainLoop); - pa_operation_unref(operation); + if (operation) { + while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) + pa_threaded_mainloop_wait(m_mainLoop); + pa_operation_unref(operation); + } else { + qWarning("PulseAudioService: failed to get source info"); + } unlock(); } |