summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOtto Ryynänen <otto.ryynanen@qt.io>2018-05-23 09:10:34 +0300
committerOtto Ryynänen <otto.ryynanen@qt.io>2018-10-30 09:18:56 +0000
commit3ee6d65377cb563d49d81c3adac0523e4ae8a0b9 (patch)
treed06d1378c5679315aa6e9d53626f14f17341f04f
parent023c48830386566042497bfac2a01c713bc5423b (diff)
Add a support for selecting the output device used by QSoundEffect
The QSoundEffect can be forced to use a specific audio output device. This is useful on a system with multiple output devices as individual QSoundeffects can use separate output devices. Due to way QAudioOutput (alternate implementation behind QSoundEffect) is implemented, QAudioDeviceInfo is used as a method of defining the output device to be used. Task-number: QTBUG-63596 Change-Id: Ibfb9894fec914726faee4e31c42ab08832693cf6 Reviewed-by: VaL Doroshchuk <valentyn.doroshchuk@qt.io>
-rw-r--r--src/multimedia/audio/qsoundeffect.cpp34
-rw-r--r--src/multimedia/audio/qsoundeffect.h2
-rw-r--r--src/multimedia/audio/qsoundeffect_pulse_p.cpp13
-rw-r--r--src/multimedia/audio/qsoundeffect_pulse_p.h2
-rw-r--r--src/multimedia/audio/qsoundeffect_qaudio_p.cpp16
-rw-r--r--src/multimedia/audio/qsoundeffect_qaudio_p.h5
-rw-r--r--tests/auto/integration/qsoundeffect/tst_qsoundeffect.cpp13
7 files changed, 66 insertions, 19 deletions
diff --git a/src/multimedia/audio/qsoundeffect.cpp b/src/multimedia/audio/qsoundeffect.cpp
index f093373ce..09085dca9 100644
--- a/src/multimedia/audio/qsoundeffect.cpp
+++ b/src/multimedia/audio/qsoundeffect.cpp
@@ -111,20 +111,34 @@ QT_BEGIN_NAMESPACE
sound effects.
*/
+static QSoundEffectPrivate *initPrivate(QSoundEffect *self, QSoundEffectPrivate *d)
+{
+ QObject::connect(d, &QSoundEffectPrivate::loopsRemainingChanged, self, &QSoundEffect::loopsRemainingChanged);
+ QObject::connect(d, &QSoundEffectPrivate::volumeChanged, self, &QSoundEffect::volumeChanged);
+ QObject::connect(d, &QSoundEffectPrivate::mutedChanged, self, &QSoundEffect::mutedChanged);
+ QObject::connect(d, &QSoundEffectPrivate::loadedChanged, self, &QSoundEffect::loadedChanged);
+ QObject::connect(d, &QSoundEffectPrivate::playingChanged, self, &QSoundEffect::playingChanged);
+ QObject::connect(d, &QSoundEffectPrivate::statusChanged, self, &QSoundEffect::statusChanged);
+ QObject::connect(d, &QSoundEffectPrivate::categoryChanged, self, &QSoundEffect::categoryChanged);
+
+ return d;
+}
/*!
Creates a QSoundEffect with the given \a parent.
*/
-QSoundEffect::QSoundEffect(QObject *parent) :
- QObject(parent)
+QSoundEffect::QSoundEffect(QObject *parent)
+ : QObject(parent)
+ , d(initPrivate(this, new QSoundEffectPrivate(this)))
+{
+}
+
+/*!
+ Creates a QSoundEffect with the given \a audioDevice and \a parent.
+*/
+QSoundEffect::QSoundEffect(const QAudioDeviceInfo &audioDevice, QObject *parent)
+ : QObject(parent)
+ , d(initPrivate(this, new QSoundEffectPrivate(audioDevice, this)))
{
- d = new QSoundEffectPrivate(this);
- connect(d, &QSoundEffectPrivate::loopsRemainingChanged, this, &QSoundEffect::loopsRemainingChanged);
- connect(d, &QSoundEffectPrivate::volumeChanged, this, &QSoundEffect::volumeChanged);
- connect(d, &QSoundEffectPrivate::mutedChanged, this, &QSoundEffect::mutedChanged);
- connect(d, &QSoundEffectPrivate::loadedChanged, this, &QSoundEffect::loadedChanged);
- connect(d, &QSoundEffectPrivate::playingChanged, this, &QSoundEffect::playingChanged);
- connect(d, &QSoundEffectPrivate::statusChanged, this, &QSoundEffect::statusChanged);
- connect(d, &QSoundEffectPrivate::categoryChanged, this, &QSoundEffect::categoryChanged);
}
/*!
diff --git a/src/multimedia/audio/qsoundeffect.h b/src/multimedia/audio/qsoundeffect.h
index b1c5fd22b..1185afe07 100644
--- a/src/multimedia/audio/qsoundeffect.h
+++ b/src/multimedia/audio/qsoundeffect.h
@@ -50,6 +50,7 @@ QT_BEGIN_NAMESPACE
class QSoundEffectPrivate;
+class QAudioDeviceInfo;
class Q_MULTIMEDIA_EXPORT QSoundEffect : public QObject
{
@@ -81,6 +82,7 @@ public:
};
explicit QSoundEffect(QObject *parent = nullptr);
+ explicit QSoundEffect(const QAudioDeviceInfo &audioDevice, QObject *parent = nullptr);
~QSoundEffect();
static QStringList supportedMimeTypes();
diff --git a/src/multimedia/audio/qsoundeffect_pulse_p.cpp b/src/multimedia/audio/qsoundeffect_pulse_p.cpp
index bbaf405b6..075e639a8 100644
--- a/src/multimedia/audio/qsoundeffect_pulse_p.cpp
+++ b/src/multimedia/audio/qsoundeffect_pulse_p.cpp
@@ -58,7 +58,7 @@
#include <private/qaudiohelpers_p.h>
#include <private/qmediaresourcepolicy_p.h>
#include <private/qmediaresourceset_p.h>
-
+#include <QAudioDeviceInfo>
#include <unistd.h>
//#define QT_PA_DEBUG
@@ -360,6 +360,12 @@ QSoundEffectPrivate::QSoundEffectPrivate(QObject* parent):
this, &QSoundEffectPrivate::handleAvailabilityChanged);
}
+QSoundEffectPrivate::QSoundEffectPrivate(const QAudioDeviceInfo &audioDevice, QObject *parent)
+ : QSoundEffectPrivate(parent)
+{
+ m_sinkName = audioDevice.deviceName();
+}
+
void QSoundEffectPrivate::handleAvailabilityChanged(bool available)
{
m_resourcesAvailable = available;
@@ -1005,8 +1011,9 @@ void QSoundEffectPrivate::createPulseStream()
}
m_pulseStream = stream;
- if (pa_stream_connect_playback(m_pulseStream, nullptr, nullptr,
- PA_STREAM_START_CORKED, nullptr, nullptr) < 0) {
+ if (pa_stream_connect_playback(m_pulseStream,
+ m_sinkName.isEmpty() ? nullptr : m_sinkName.toLatin1().constData(),
+ nullptr, PA_STREAM_START_CORKED, nullptr, nullptr) < 0) {
qWarning("QSoundEffect(pulseaudio): Failed to connect stream, error = %s",
pa_strerror(pa_context_errno(pulseDaemon()->context())));
}
diff --git a/src/multimedia/audio/qsoundeffect_pulse_p.h b/src/multimedia/audio/qsoundeffect_pulse_p.h
index 8f74d67e7..e0073f0d5 100644
--- a/src/multimedia/audio/qsoundeffect_pulse_p.h
+++ b/src/multimedia/audio/qsoundeffect_pulse_p.h
@@ -73,6 +73,7 @@ class QSoundEffectPrivate : public QObject
Q_OBJECT
public:
explicit QSoundEffectPrivate(QObject* parent);
+ explicit QSoundEffectPrivate(const QAudioDeviceInfo &audioDevice, QObject *parent);
~QSoundEffectPrivate();
static QStringList supportedMimeTypes();
@@ -150,6 +151,7 @@ private:
static void stream_adjust_prebuffer_callback(pa_stream *s, int success, void *userdata);
pa_stream *m_pulseStream = nullptr;
+ QString m_sinkName;
int m_sinkInputId = -1;
pa_sample_spec m_pulseSpec;
int m_pulseBufferSize = 0;
diff --git a/src/multimedia/audio/qsoundeffect_qaudio_p.cpp b/src/multimedia/audio/qsoundeffect_qaudio_p.cpp
index 3f315fa28..e501d3217 100644
--- a/src/multimedia/audio/qsoundeffect_qaudio_p.cpp
+++ b/src/multimedia/audio/qsoundeffect_qaudio_p.cpp
@@ -66,6 +66,12 @@ QSoundEffectPrivate::QSoundEffectPrivate(QObject *parent):
{
}
+QSoundEffectPrivate::QSoundEffectPrivate(const QAudioDeviceInfo &audioDevice, QObject *parent)
+ : QObject(parent)
+ , d(new PrivateSoundSource(this, audioDevice))
+{
+}
+
QSoundEffectPrivate::~QSoundEffectPrivate()
{
}
@@ -309,8 +315,9 @@ void QSoundEffectPrivate::setCategory(const QString &category)
}
}
-PrivateSoundSource::PrivateSoundSource(QSoundEffectPrivate *s):
- QIODevice(s)
+PrivateSoundSource::PrivateSoundSource(QSoundEffectPrivate *s, const QAudioDeviceInfo &audioDevice)
+ : QIODevice(s)
+ , m_audioDevice(audioDevice)
{
soundeffect = s;
m_category = QLatin1String("game");
@@ -328,7 +335,10 @@ void PrivateSoundSource::sampleReady()
disconnect(m_sample, &QSample::error, this, &PrivateSoundSource::decoderError);
disconnect(m_sample, &QSample::ready, this, &PrivateSoundSource::sampleReady);
if (!m_audioOutput) {
- m_audioOutput = new QAudioOutput(m_sample->format());
+ if (m_audioDevice.isNull())
+ m_audioOutput = new QAudioOutput(m_sample->format());
+ else
+ m_audioOutput = new QAudioOutput(m_audioDevice, m_sample->format());
connect(m_audioOutput, &QAudioOutput::stateChanged, this, &PrivateSoundSource::stateChanged);
if (!m_muted)
m_audioOutput->setVolume(m_volume);
diff --git a/src/multimedia/audio/qsoundeffect_qaudio_p.h b/src/multimedia/audio/qsoundeffect_qaudio_p.h
index c02a85969..a3a48f60d 100644
--- a/src/multimedia/audio/qsoundeffect_qaudio_p.h
+++ b/src/multimedia/audio/qsoundeffect_qaudio_p.h
@@ -66,7 +66,7 @@ class PrivateSoundSource : public QIODevice
friend class QSoundEffectPrivate;
Q_OBJECT
public:
- PrivateSoundSource(QSoundEffectPrivate *s);
+ PrivateSoundSource(QSoundEffectPrivate *s, const QAudioDeviceInfo &audioDevice = QAudioDeviceInfo());
~PrivateSoundSource() {}
qint64 readData(char *data, qint64 len) override;
@@ -90,7 +90,7 @@ private:
bool m_sampleReady = false;
qint64 m_offset = 0;
QString m_category;
-
+ QAudioDeviceInfo m_audioDevice;
QSoundEffectPrivate *soundeffect = nullptr;
};
@@ -102,6 +102,7 @@ class QSoundEffectPrivate : public QObject
public:
explicit QSoundEffectPrivate(QObject *parent);
+ explicit QSoundEffectPrivate(const QAudioDeviceInfo &audioDevice, QObject *parent);
~QSoundEffectPrivate();
static QStringList supportedMimeTypes();
diff --git a/tests/auto/integration/qsoundeffect/tst_qsoundeffect.cpp b/tests/auto/integration/qsoundeffect/tst_qsoundeffect.cpp
index fa98c8b16..7cbd57007 100644
--- a/tests/auto/integration/qsoundeffect/tst_qsoundeffect.cpp
+++ b/tests/auto/integration/qsoundeffect/tst_qsoundeffect.cpp
@@ -60,6 +60,7 @@ private slots:
void testSetSourceWhileLoading();
void testSetSourceWhilePlaying();
+ void testSupportedMimeTypes_data();
void testSupportedMimeTypes();
void testCorruptFile();
void testPlaying24Bits();
@@ -387,9 +388,19 @@ void tst_QSoundEffect::testSetSourceWhilePlaying()
}
}
+void tst_QSoundEffect::testSupportedMimeTypes_data()
+{
+ // Verify also passing of audio device info as parameter
+ QTest::addColumn<QSoundEffect*>("instance");
+ QTest::newRow("without QAudioDeviceInfo") << sound;
+ QAudioDeviceInfo deviceInfo(QAudioDeviceInfo::defaultOutputDevice());
+ QTest::newRow("with QAudioDeviceInfo") << new QSoundEffect(deviceInfo, this);
+}
+
void tst_QSoundEffect::testSupportedMimeTypes()
{
- QStringList mimeTypes = sound->supportedMimeTypes();
+ QFETCH(QSoundEffect*, instance);
+ QStringList mimeTypes = instance->supportedMimeTypes();
QVERIFY(!mimeTypes.empty());
QVERIFY(mimeTypes.indexOf(QLatin1String("audio/wav")) != -1 ||
mimeTypes.indexOf(QLatin1String("audio/x-wav")) != -1 ||