summaryrefslogtreecommitdiff
path: root/src/multimedia
diff options
context:
space:
mode:
authorMichael Goddard <michael.goddard@nokia.com>2012-04-13 13:51:09 +1000
committerQt by Nokia <qt-info@nokia.com>2012-04-16 10:56:34 +0200
commit5f7b64346db43a6aa3ea2bbc15c63d4864f4d005 (patch)
tree845838026bba3e5236999abcab7f0bd9b39d6ec3 /src/multimedia
parent8441d2e32e3bae40640a1584d1d1d1e82980d718 (diff)
downloadqtmultimedia-5f7b64346db43a6aa3ea2bbc15c63d4864f4d005.tar.gz
Expose the audio category information for streams.
QAudioOutput and QSoundEffect now have a category property so that system volume mixing or processing can be applied. Initially just pulseaudio supports this but Windows Vista etc should also work. Change-Id: I6855b08367e5a055ac7dfcffd644c98bfd7c5a4e Reviewed-by: Ling Hu <ling.hu@nokia.com>
Diffstat (limited to 'src/multimedia')
-rw-r--r--src/multimedia/audio/qaudiooutput.cpp35
-rw-r--r--src/multimedia/audio/qaudiooutput.h3
-rw-r--r--src/multimedia/audio/qaudiosystem.h2
-rw-r--r--src/multimedia/audio/qsoundeffect.cpp52
-rw-r--r--src/multimedia/audio/qsoundeffect.h5
-rw-r--r--src/multimedia/audio/qsoundeffect_pulse_p.cpp44
-rw-r--r--src/multimedia/audio/qsoundeffect_pulse_p.h6
-rw-r--r--src/multimedia/audio/qsoundeffect_qmedia_p.cpp14
-rw-r--r--src/multimedia/audio/qsoundeffect_qmedia_p.h6
9 files changed, 164 insertions, 3 deletions
diff --git a/src/multimedia/audio/qaudiooutput.cpp b/src/multimedia/audio/qaudiooutput.cpp
index 8647ecdb5..685667ee5 100644
--- a/src/multimedia/audio/qaudiooutput.cpp
+++ b/src/multimedia/audio/qaudiooutput.cpp
@@ -364,6 +364,41 @@ qreal QAudioOutput::volume() const
}
/*!
+ Returns the audio category of this audio stream.
+
+ Some platforms can group audio streams into categories
+ and manage their volumes independently, or display them
+ in a system mixer control. You can set this property to
+ allow the platform to distinguish the purpose of your streams.
+
+ \sa setCategory()
+*/
+QString QAudioOutput::category() const
+{
+ return d->category();
+}
+
+/*!
+ Sets the audio category of this audio stream.
+
+ Some platforms can group audio streams into categories
+ and manage their volumes independently, or display them
+ in a system mixer control. You can set this property to
+ allow the platform to distinguish the purpose of your streams.
+
+ Not all platforms support audio stream categorization. In this
+ case, the function call will be ignored.
+
+ Changing an audio output stream's category while it is opened
+ will not take effect until it is reopened.
+ \sa category()
+*/
+void QAudioOutput::setCategory(const QString &category)
+{
+ d->setCategory(category);
+}
+
+/*!
\fn QAudioOutput::stateChanged(QAudio::State state)
This signal is emitted when the device \a state has changed.
This is the current state of the audio output.
diff --git a/src/multimedia/audio/qaudiooutput.h b/src/multimedia/audio/qaudiooutput.h
index 400272b10..84725e316 100644
--- a/src/multimedia/audio/qaudiooutput.h
+++ b/src/multimedia/audio/qaudiooutput.h
@@ -100,6 +100,9 @@ public:
void setVolume(qreal);
qreal volume() const;
+ QString category() const;
+ void setCategory(const QString &category);
+
Q_SIGNALS:
void stateChanged(QAudio::State);
void notify();
diff --git a/src/multimedia/audio/qaudiosystem.h b/src/multimedia/audio/qaudiosystem.h
index aaf1d5786..390cc9733 100644
--- a/src/multimedia/audio/qaudiosystem.h
+++ b/src/multimedia/audio/qaudiosystem.h
@@ -97,6 +97,8 @@ public:
virtual QAudioFormat format() const = 0;
virtual void setVolume(qreal) {}
virtual qreal volume() const { return 1.0; }
+ virtual QString category() const { return QString(); }
+ virtual void setCategory(const QString &) { }
Q_SIGNALS:
void errorChanged(QAudio::Error);
diff --git a/src/multimedia/audio/qsoundeffect.cpp b/src/multimedia/audio/qsoundeffect.cpp
index ffaeb3418..6526f1dcb 100644
--- a/src/multimedia/audio/qsoundeffect.cpp
+++ b/src/multimedia/audio/qsoundeffect.cpp
@@ -218,6 +218,7 @@ QSoundEffect::QSoundEffect(QObject *parent) :
connect(d, SIGNAL(loadedChanged()), SIGNAL(loadedChanged()));
connect(d, SIGNAL(playingChanged()), SIGNAL(playingChanged()));
connect(d, SIGNAL(statusChanged()), SIGNAL(statusChanged()));
+ connect(d, SIGNAL(categoryChanged()), SIGNAL(categoryChanged()));
}
/*!
@@ -366,6 +367,57 @@ QSoundEffect::Status QSoundEffect::status() const
return d->status();
}
+/*!
+ \qmlproperty string QtMultimedia5::SoundEffect::category
+ \property QSoundEffect::category
+
+ This property contains the \e category of this sound effect.
+
+ Some platforms can perform different audio routing
+ for different categories, or may allow the user to
+ set different volume levels for different categories.
+
+ This setting will be ignored on platforms that do not
+ support audio categories.
+*/
+/*!
+ Returns the current \e category for this sound effect.
+
+ Some platforms can perform different audio routing
+ for different categories, or may allow the user to
+ set different volume levels for different categories.
+
+ This setting will be ignored on platforms that do not
+ support audio categories.
+
+ \sa setCategory()
+*/
+QString QSoundEffect::category() const
+{
+ return d->category();
+}
+
+/*!
+ Sets the \e category of this sound effect to \a category.
+
+ Some platforms can perform different audio routing
+ for different categories, or may allow the user to
+ set different volume levels for different categories.
+
+ This setting will be ignored on platforms that do not
+ support audio categories.
+
+ If this setting is changed while a sound effect is playing
+ it will only take effect when the sound effect has stopped
+ playing.
+
+ \sa category()
+ */
+void QSoundEffect::setCategory(const QString &category)
+{
+ d->setCategory(category);
+}
+
/*!
\qmlmethod QtMultimedia5::SoundEffect::stop()
diff --git a/src/multimedia/audio/qsoundeffect.h b/src/multimedia/audio/qsoundeffect.h
index 44d2f5ba5..f3de7ec17 100644
--- a/src/multimedia/audio/qsoundeffect.h
+++ b/src/multimedia/audio/qsoundeffect.h
@@ -68,6 +68,7 @@ class Q_MULTIMEDIA_EXPORT QSoundEffect : public QObject
Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged)
Q_PROPERTY(bool playing READ isPlaying NOTIFY playingChanged)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(QString category READ category WRITE setCategory NOTIFY categoryChanged)
Q_ENUMS(Loop)
Q_ENUMS(Status)
@@ -108,6 +109,9 @@ public:
bool isPlaying() const;
Status status() const;
+ QString category() const;
+ void setCategory(const QString &category);
+
Q_SIGNALS:
void sourceChanged();
void loopCountChanged();
@@ -117,6 +121,7 @@ Q_SIGNALS:
void loadedChanged();
void playingChanged();
void statusChanged();
+ void categoryChanged();
public Q_SLOTS:
void play();
diff --git a/src/multimedia/audio/qsoundeffect_pulse_p.cpp b/src/multimedia/audio/qsoundeffect_pulse_p.cpp
index 609e668fd..3b9278c7d 100644
--- a/src/multimedia/audio/qsoundeffect_pulse_p.cpp
+++ b/src/multimedia/audio/qsoundeffect_pulse_p.cpp
@@ -351,7 +351,8 @@ QSoundEffectPrivate::QSoundEffectPrivate(QObject* parent):
m_volume(100),
m_loopCount(1),
m_runningCount(0),
- m_sample(0) ,
+ m_sample(0),
+ m_reloadCategory(false),
m_position(0)
{
m_ref = new QSoundEffectRef(this);
@@ -373,6 +374,32 @@ void QSoundEffectPrivate::release()
this->deleteLater();
}
+QString QSoundEffectPrivate::category() const
+{
+ return m_category;
+}
+
+void QSoundEffectPrivate::setCategory(const QString &category)
+{
+ if (m_category != category) {
+ m_category = category;
+ if (m_playing || m_playQueued) {
+ // Currently playing, we need to disconnect when
+ // playback stops
+ m_reloadCategory = true;
+ } else if (m_pulseStream) {
+ // We have to disconnect and reconnect
+ unloadPulseStream();
+ createPulseStream();
+ } else {
+ // Well, next time we create the pulse stream
+ // it should be set
+ }
+
+ emit categoryChanged();
+ }
+}
+
QSoundEffectPrivate::~QSoundEffectPrivate()
{
m_ref->release();
@@ -700,6 +727,7 @@ void QSoundEffectPrivate::unloadPulseStream()
pa_stream_unref(m_pulseStream);
disconnect(pulseDaemon(), SIGNAL(volumeChanged()), this, SLOT(updateVolume()));
m_pulseStream = 0;
+ m_reloadCategory = false; // category will be reloaded when we connect anyway
}
}
@@ -808,11 +836,16 @@ void QSoundEffectPrivate::stop()
setPlaying(false);
PulseDaemonLocker locker;
m_stopping = true;
- if (m_pulseStream)
+ if (m_pulseStream) {
emptyStream();
+ if (m_reloadCategory) {
+ unloadPulseStream(); // upon play we reconnect anyway
+ }
+ }
setLoopsRemaining(0);
m_position = 0;
m_playQueued = false;
+ m_reloadCategory = false;
}
void QSoundEffectPrivate::underRun()
@@ -846,7 +879,12 @@ void QSoundEffectPrivate::createPulseStream()
#endif
pa_proplist *propList = pa_proplist_new();
- pa_proplist_sets(propList, PA_PROP_MEDIA_ROLE, "soundeffect");
+ if (m_category.isNull()) {
+ // Meant to be one of the strings "video", "music", "game", "event", "phone", "animation", "production", "a11y", "test"
+ pa_proplist_sets(propList, PA_PROP_MEDIA_ROLE, "game");
+ } else {
+ pa_proplist_sets(propList, PA_PROP_MEDIA_ROLE, m_category.toLatin1().constData());
+ }
pa_stream *stream = pa_stream_new_with_proplist(pulseDaemon()->context(), m_name.constData(), &m_pulseSpec, 0, propList);
pa_proplist_free(propList);
diff --git a/src/multimedia/audio/qsoundeffect_pulse_p.h b/src/multimedia/audio/qsoundeffect_pulse_p.h
index 08c010493..6c7202c24 100644
--- a/src/multimedia/audio/qsoundeffect_pulse_p.h
+++ b/src/multimedia/audio/qsoundeffect_pulse_p.h
@@ -94,6 +94,9 @@ public:
void release();
+ QString category() const;
+ void setCategory(const QString &category);
+
public Q_SLOTS:
void play();
void stop();
@@ -105,6 +108,7 @@ Q_SIGNALS:
void loadedChanged();
void playingChanged();
void statusChanged();
+ void categoryChanged();
private Q_SLOTS:
void decoderError();
@@ -157,6 +161,8 @@ private:
int m_runningCount;
QUrl m_source;
QByteArray m_name;
+ QString m_category;
+ bool m_reloadCategory;
QSample *m_sample;
int m_position;
diff --git a/src/multimedia/audio/qsoundeffect_qmedia_p.cpp b/src/multimedia/audio/qsoundeffect_qmedia_p.cpp
index dd83f60f1..66d05e662 100644
--- a/src/multimedia/audio/qsoundeffect_qmedia_p.cpp
+++ b/src/multimedia/audio/qsoundeffect_qmedia_p.cpp
@@ -250,6 +250,20 @@ void QSoundEffectPrivate::setLoopsRemaining(int loopsRemaining)
emit loopsRemainingChanged();
}
+/* Categories are ignored */
+QString QSoundEffectPrivate::category() const
+{
+ return m_category;
+}
+
+void QSoundEffectPrivate::setCategory(const QString &category)
+{
+ if (m_category != category && !m_playing) {
+ m_category = category;
+ emit categoryChanged();
+ }
+}
+
QT_END_NAMESPACE
#include "moc_qsoundeffect_qmedia_p.cpp"
diff --git a/src/multimedia/audio/qsoundeffect_qmedia_p.h b/src/multimedia/audio/qsoundeffect_qmedia_p.h
index 159c60c15..cc4786c44 100644
--- a/src/multimedia/audio/qsoundeffect_qmedia_p.h
+++ b/src/multimedia/audio/qsoundeffect_qmedia_p.h
@@ -91,6 +91,10 @@ public:
void release();
+ // Categories are not really supported with QMediaPlayer
+ QString category() const;
+ void setCategory(const QString &);
+
public Q_SLOTS:
void play();
void stop();
@@ -102,6 +106,7 @@ Q_SIGNALS:
void loadedChanged();
void playingChanged();
void statusChanged();
+ void categoryChanged();
private Q_SLOTS:
void stateChanged(QMediaPlayer::State);
@@ -118,6 +123,7 @@ private:
bool m_playing;
QSoundEffect::Status m_status;
QMediaPlayer *m_player;
+ QString m_category;
};
QT_END_NAMESPACE