summaryrefslogtreecommitdiff
path: root/src/multimedia/audio
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2016-03-21 14:26:15 +0100
committerLiang Qi <liang.qi@theqtcompany.com>2016-03-21 14:26:22 +0100
commite757890f4a5669b396039211902224f31666725a (patch)
treebb220ff8b9d8d4a64ce5f197a4b39e3e5965da63 /src/multimedia/audio
parentcaf0cbca71231dbb6403108ba41d2117d3ce6c6d (diff)
parent71a6b1b62041981f894cb2b6589fce92f137bbc4 (diff)
downloadqtmultimedia-e757890f4a5669b396039211902224f31666725a.tar.gz
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.cpp214
-rw-r--r--src/multimedia/audio/qsoundeffect_pulse_p.h13
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