diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2016-03-21 14:26:15 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2016-03-21 14:26:22 +0100 |
commit | e757890f4a5669b396039211902224f31666725a (patch) | |
tree | bb220ff8b9d8d4a64ce5f197a4b39e3e5965da63 /src/multimedia/audio | |
parent | caf0cbca71231dbb6403108ba41d2117d3ce6c6d (diff) | |
parent | 71a6b1b62041981f894cb2b6589fce92f137bbc4 (diff) |
Merge remote-tracking branch 'origin/5.6' into 5.7
Change-Id: Ieb1a3081907093e31e8c8b7f95993bb3b2173672
Diffstat (limited to 'src/multimedia/audio')
-rw-r--r-- | src/multimedia/audio/qsoundeffect_pulse_p.cpp | 214 | ||||
-rw-r--r-- | src/multimedia/audio/qsoundeffect_pulse_p.h | 13 |
2 files changed, 57 insertions, 170 deletions
diff --git a/src/multimedia/audio/qsoundeffect_pulse_p.cpp b/src/multimedia/audio/qsoundeffect_pulse_p.cpp index 472c01489..79d1d96ab 100644 --- a/src/multimedia/audio/qsoundeffect_pulse_p.cpp +++ b/src/multimedia/audio/qsoundeffect_pulse_p.cpp @@ -55,10 +55,7 @@ #include "qsoundeffect_pulse_p.h" -#if defined(Q_WS_MAEMO_6) || defined(NEMO_AUDIO) -#include <pulse/ext-stream-restore.h> -#endif - +#include <private/qaudiohelpers_p.h> #include <private/qmediaresourcepolicy_p.h> #include <private/qmediaresourceset_p.h> @@ -130,26 +127,9 @@ public: return m_context; } - inline pa_cvolume * calcVolume(pa_cvolume *dest, int soundEffectVolume) - { - pa_volume_t v = m_vol * soundEffectVolume / 100; - for (int i = 0; i < dest->channels; ++i) - dest->values[i] = v; - return dest; - } - - void updateStatus(const pa_cvolume& volume) - { - if (m_vol != pa_cvolume_max(&volume)) { - m_vol = pa_cvolume_max(&volume); - emit volumeChanged(); - } - } - Q_SIGNALS: void contextReady(); void contextFailed(); - void volumeChanged(); private Q_SLOTS: void onContextFailed() @@ -164,8 +144,6 @@ private Q_SLOTS: void prepare() { - m_vol = PA_VOLUME_NORM; - m_context = 0; m_mainLoop = pa_threaded_mainloop_new(); if (m_mainLoop == 0) { @@ -238,11 +216,6 @@ private: case PA_CONTEXT_SETTING_NAME: break; case PA_CONTEXT_READY: - #if defined(Q_WS_MAEMO_6) || defined(NEMO_AUDIO) - pa_ext_stream_restore_read(c, &stream_restore_info_callback, self); - pa_ext_stream_restore_set_subscribe_cb(c, &stream_restore_monitor_callback, self); - pa_ext_stream_restore_subscribe(c, 1, 0, self); - #endif QMetaObject::invokeMethod(self, "contextReady", Qt::QueuedConnection); break; case PA_CONTEXT_FAILED: @@ -253,37 +226,6 @@ private: } } -#if defined(Q_WS_MAEMO_6) || defined(NEMO_AUDIO) - - static void stream_restore_monitor_callback(pa_context *c, void *userdata) - { - PulseDaemon *self = reinterpret_cast<PulseDaemon*>(userdata); - pa_ext_stream_restore_read(c, &stream_restore_info_callback, self); - } - - static void stream_restore_info_callback(pa_context *c, - const pa_ext_stream_restore_info *info, - int eol, void *userdata) - { - Q_UNUSED(c) - - PulseDaemon *self = reinterpret_cast<PulseDaemon*>(userdata); - - if (!eol) { - if (QString(info->name).startsWith(QLatin1String("sink-input-by-media-role:x-maemo"))) { -#ifdef QT_PA_DEBUG - qDebug() << "x-maemo volume =(" << info->volume.values[0] * 100 / PA_VOLUME_NORM << "," - << info->volume.values[1] * 100 / PA_VOLUME_NORM << "), " - << "mute = " << info->mute; -#endif - self->updateStatus(info->volume); - } - } - } -#endif - - pa_volume_t m_vol; - bool m_prepared; pa_context *m_context; pa_threaded_mainloop *m_mainLoop; @@ -391,9 +333,6 @@ QSoundEffectPrivate::QSoundEffectPrivate(QObject* parent): m_sample(0), m_position(0), m_resourcesAvailable(false) -#if defined(Q_WS_MAEMO_6) || defined(NEMO_AUDIO) - , m_customVolume(false) -#endif { m_ref = new QSoundEffectRef(this); pa_sample_spec_init(&m_pulseSpec); @@ -544,60 +483,32 @@ void QSoundEffectPrivate::setLoopCount(int loopCount) qreal QSoundEffectPrivate::volume() const { + QReadLocker locker(&m_volumeLock); return m_volume; } void QSoundEffectPrivate::setVolume(qreal volume) { -#if defined(Q_WS_MAEMO_6) || defined(NEMO_AUDIO) - m_customVolume = true; -#endif - m_volume = volume; - emit volumeChanged(); - updateVolume(); -} + QWriteLocker locker(&m_volumeLock); -void QSoundEffectPrivate::updateVolume() -{ - if (m_sinkInputId < 0) + if (qFuzzyCompare(m_volume, volume)) return; -#if defined(Q_WS_MAEMO_6) || defined(NEMO_AUDIO) - if (!m_customVolume) - return; -#endif - PulseDaemonLocker locker; - pa_cvolume volume; - volume.channels = m_pulseSpec.channels; - if (pulseDaemon()->context()) - pa_operation_unref(pa_context_set_sink_input_volume(pulseDaemon()->context(), m_sinkInputId, pulseDaemon()->calcVolume(&volume, qRound(m_volume * 100)), setvolume_callback, m_ref->getRef())); - Q_ASSERT(pa_cvolume_valid(&volume)); -#ifdef QT_PA_DEBUG - qDebug() << this << "updateVolume =" << pa_cvolume_max(&volume); -#endif + + m_volume = qBound(qreal(0), volume, qreal(1)); + emit volumeChanged(); } bool QSoundEffectPrivate::isMuted() const { + QReadLocker locker(&m_volumeLock); return m_muted; } void QSoundEffectPrivate::setMuted(bool muted) { + QWriteLocker locker(&m_volumeLock); m_muted = muted; emit mutedChanged(); - updateMuted(); -} - -void QSoundEffectPrivate::updateMuted() -{ - if (m_sinkInputId < 0) - return; - PulseDaemonLocker locker; - if (pulseDaemon()->context()) - pa_operation_unref(pa_context_set_sink_input_mute(pulseDaemon()->context(), m_sinkInputId, m_muted, setmuted_callback, m_ref->getRef())); -#ifdef QT_PA_DEBUG - qDebug() << this << "updateMuted = " << m_muted; -#endif } bool QSoundEffectPrivate::isLoaded() const @@ -807,7 +718,6 @@ void QSoundEffectPrivate::unloadPulseStream() pa_stream_set_underflow_callback(m_pulseStream, 0, 0); pa_stream_disconnect(m_pulseStream); pa_stream_unref(m_pulseStream); - disconnect(pulseDaemon(), SIGNAL(volumeChanged()), this, SLOT(updateVolume())); disconnect(pulseDaemon(), SIGNAL(contextFailed()), this, SLOT(contextFailed())); m_pulseStream = 0; m_reloadCategory = false; // category will be reloaded when we connect anyway @@ -828,11 +738,8 @@ void QSoundEffectPrivate::prepare() << "actual writeBytes =" << writeBytes << "m_playQueued =" << m_playQueued; #endif - m_position = int(writeBytes); - if (pa_stream_write(m_pulseStream, reinterpret_cast<void *>(const_cast<char*>(m_sample->data().data())), writeBytes, - stream_write_done_callback, 0, PA_SEEK_RELATIVE) != 0) { - qWarning("QSoundEffect(pulseaudio): pa_stream_write, error = %s", pa_strerror(pa_context_errno(pulseDaemon()->context()))); - } + m_position = writeToStream(m_sample->data().data(), writeBytes); + if (m_playQueued) { m_playQueued = false; setLoopsRemaining(m_loopCount); @@ -860,15 +767,13 @@ void QSoundEffectPrivate::uploadSample() } } - int writtenBytes = 0; int writableSize = int(pa_stream_writable_size(m_pulseStream)); int firstPartLength = qMin(m_sample->data().size() - m_position, writableSize); - if (pa_stream_write(m_pulseStream, reinterpret_cast<void *>(const_cast<char*>(m_sample->data().data()) + m_position), - firstPartLength, stream_write_done_callback, 0, PA_SEEK_RELATIVE) != 0) { - qWarning("QSoundEffect(pulseaudio): pa_stream_write, error = %s", pa_strerror(pa_context_errno(pulseDaemon()->context()))); - } - writtenBytes = firstPartLength; - m_position += firstPartLength; + + int writtenBytes = writeToStream(m_sample->data().data() + m_position, + firstPartLength); + + m_position += writtenBytes; if (m_position == m_sample->data().size()) { m_position = 0; if (m_runningCount > 0) @@ -877,11 +782,8 @@ void QSoundEffectPrivate::uploadSample() { while (writtenBytes < writableSize) { int writeSize = qMin(writableSize - writtenBytes, m_sample->data().size()); - if (pa_stream_write(m_pulseStream, reinterpret_cast<void *>(const_cast<char*>(m_sample->data().data())), - writeSize, stream_write_done_callback, 0, PA_SEEK_RELATIVE) != 0) { - qWarning("QSoundEffect(pulseaudio): pa_stream_write, error = %s", pa_strerror(pa_context_errno(pulseDaemon()->context()))); - } - writtenBytes += writeSize; + writtenBytes += writeToStream(m_sample->data().data(), writeSize); + if (writeSize < m_sample->data().size()) { m_position = writeSize; break; @@ -899,6 +801,39 @@ void QSoundEffectPrivate::uploadSample() #endif } +int QSoundEffectPrivate::writeToStream(const void *data, int size) +{ + m_volumeLock.lockForRead(); + qreal volume = m_muted ? 0 : m_volume; + m_volumeLock.unlock(); + pa_free_cb_t writeDoneCb = stream_write_done_callback; + + if (volume < 1.0f) { + // Don't use PulseAudio volume, as it might affect all other streams of the same category + // or even affect the system volume if flat volumes are enabled + void *dest = NULL; + size_t nbytes = size; + if (pa_stream_begin_write(m_pulseStream, &dest, &nbytes) < 0) { + qWarning("QSoundEffect(pulseaudio): pa_stream_begin_write, error = %s", + pa_strerror(pa_context_errno(pulseDaemon()->context()))); + return 0; + } + + size = int(nbytes); + QAudioHelperInternal::qMultiplySamples(volume, m_sample->format(), data, dest, size); + data = dest; + writeDoneCb = NULL; + } + + if (pa_stream_write(m_pulseStream, data, size, writeDoneCb, 0, PA_SEEK_RELATIVE) < 0) { + qWarning("QSoundEffect(pulseaudio): pa_stream_write, error = %s", + pa_strerror(pa_context_errno(pulseDaemon()->context()))); + return 0; + } + + return size; +} + void QSoundEffectPrivate::playSample() { #ifdef QT_PA_DEBUG @@ -945,8 +880,6 @@ void QSoundEffectPrivate::streamReady() #endif PulseDaemonLocker locker; m_sinkInputId = pa_stream_get_index(m_pulseStream); - updateMuted(); - updateVolume(); #ifdef QT_PA_DEBUG const pa_buffer_attr *realBufAttr = pa_stream_get_buffer_attr(m_pulseStream); qDebug() << this << "m_sinkInputId =" << m_sinkInputId @@ -972,7 +905,6 @@ void QSoundEffectPrivate::createPulseStream() pa_stream *stream = pa_stream_new_with_proplist(pulseDaemon()->context(), m_name.constData(), &m_pulseSpec, 0, propList); pa_proplist_free(propList); - connect(pulseDaemon(), SIGNAL(volumeChanged()), this, SLOT(updateVolume())); connect(pulseDaemon(), SIGNAL(contextFailed()), this, SLOT(contextFailed())); if (stream == 0) { @@ -1000,9 +932,7 @@ void QSoundEffectPrivate::createPulseStream() #else if (pa_stream_connect_playback(m_pulseStream, 0, 0, #endif - m_muted ? pa_stream_flags_t(PA_STREAM_START_MUTED | PA_STREAM_START_CORKED) - : pa_stream_flags_t(PA_STREAM_START_UNMUTED | PA_STREAM_START_CORKED), - 0, 0) < 0) { + PA_STREAM_START_CORKED, 0, 0) < 0) { qWarning("QSoundEffect(pulseaudio): Failed to connect stream, error = %s", pa_strerror(pa_context_errno(pulseDaemon()->context()))); } @@ -1121,46 +1051,6 @@ void QSoundEffectPrivate::stream_adjust_prebuffer_callback(pa_stream *s, int suc QMetaObject::invokeMethod(self, "streamReady", Qt::QueuedConnection); } -void QSoundEffectPrivate::setvolume_callback(pa_context *c, int success, void *userdata) -{ -#ifdef QT_PA_DEBUG - qDebug() << "setvolume_callback"; -#endif - Q_UNUSED(c); - Q_UNUSED(userdata); - QSoundEffectRef *ref = reinterpret_cast<QSoundEffectRef*>(userdata); - QSoundEffectPrivate *self = ref->soundEffect(); - ref->release(); - if (!self) - return; -#ifdef QT_PA_DEBUG - qDebug() << self << "setvolume_callback"; -#endif - if (!success) { - qWarning("QSoundEffect(pulseaudio): faild to set volume"); - } -} - -void QSoundEffectPrivate::setmuted_callback(pa_context *c, int success, void *userdata) -{ -#ifdef QT_PA_DEBUG - qDebug() << "setmuted_callback"; -#endif - Q_UNUSED(c); - Q_UNUSED(userdata); - QSoundEffectRef *ref = reinterpret_cast<QSoundEffectRef*>(userdata); - QSoundEffectPrivate *self = ref->soundEffect(); - ref->release(); - if (!self) - return; -#ifdef QT_PA_DEBUG - qDebug() << self << "setmuted_callback"; -#endif - if (!success) { - qWarning("QSoundEffect(pulseaudio): faild to set muted"); - } -} - void QSoundEffectPrivate::stream_underrun_callback(pa_stream *s, void *userdata) { Q_UNUSED(s); diff --git a/src/multimedia/audio/qsoundeffect_pulse_p.h b/src/multimedia/audio/qsoundeffect_pulse_p.h index 259d2e046..6bf2416cf 100644 --- a/src/multimedia/audio/qsoundeffect_pulse_p.h +++ b/src/multimedia/audio/qsoundeffect_pulse_p.h @@ -56,6 +56,7 @@ #include <QtCore/qobject.h> #include <QtCore/qdatetime.h> +#include <QtCore/qreadwritelock.h> #include <qmediaplayer.h> #include <pulse/pulseaudio.h> #include "qsamplecache_p.h" @@ -117,8 +118,6 @@ private Q_SLOTS: void prepare(); void streamReady(); void emptyComplete(void *stream); - void updateVolume(); - void updateMuted(); void handleAvailabilityChanged(bool available); @@ -130,6 +129,8 @@ private: void createPulseStream(); void unloadPulseStream(); + int writeToStream(const void *data, int size); + void setPlaying(bool playing); void setStatus(QSoundEffect::Status status); void setLoopsRemaining(int loopsRemaining); @@ -142,8 +143,6 @@ private: static void stream_write_done_callback(void *p); static void stream_adjust_prebuffer_callback(pa_stream *s, int success, void *userdata); static void stream_reset_buffer_callback(pa_stream *s, int success, void *userdata); - static void setvolume_callback(pa_context *c, int success, void *userdata); - static void setmuted_callback(pa_context *c, int success, void *userdata); pa_stream *m_pulseStream; int m_sinkInputId; @@ -171,11 +170,9 @@ private: bool m_resourcesAvailable; - QMediaPlayerResourceSetInterface *m_resources; + mutable QReadWriteLock m_volumeLock; -#if defined(Q_WS_MAEMO_6) || defined(NEMO_AUDIO) - bool m_customVolume; -#endif + QMediaPlayerResourceSetInterface *m_resources; }; QT_END_NAMESPACE |