summaryrefslogtreecommitdiffstats
path: root/src/multimedia
diff options
context:
space:
mode:
authorMithra Pattison <mithra.pattison@nokia.com>2011-12-22 15:12:03 +1000
committerQt by Nokia <qt-info@nokia.com>2011-12-30 05:03:45 +0100
commitf9ec11a25e0d04485745fbb9d9fb929da3459826 (patch)
treefbbdc623b99b9da4eeffbc502324f94d2e40942f /src/multimedia
parentc13a13c4866bdacc066d9921290eed41e1b54a8b (diff)
Add new implementation of QSound class
Added a re-implementation of QSound, using functionality derived from QSoundEffect. QSound API remains the same as the original 4.x version. It offers both a static interface (with auto resource cleanup on sound completion), as well as an object instance interface for more detailed control. Change-Id: I85c00dd88547f8dea9b1e1ef2da31d2f2e28a172 Reviewed-by: Michael Goddard <michael.goddard@nokia.com>
Diffstat (limited to 'src/multimedia')
-rw-r--r--src/multimedia/effects/effects.pri6
-rw-r--r--src/multimedia/effects/qsound.cpp236
-rw-r--r--src/multimedia/effects/qsound.h93
-rw-r--r--src/multimedia/effects/qsoundeffect.cpp17
-rw-r--r--src/multimedia/effects/qsoundeffect.h3
-rw-r--r--src/multimedia/effects/qsoundeffect_pulse_p.cpp30
-rw-r--r--src/multimedia/effects/qsoundeffect_pulse_p.h3
-rw-r--r--src/multimedia/effects/qsoundeffect_qmedia_p.cpp30
-rw-r--r--src/multimedia/effects/qsoundeffect_qmedia_p.h3
9 files changed, 403 insertions, 18 deletions
diff --git a/src/multimedia/effects/effects.pri b/src/multimedia/effects/effects.pri
index f83f7296f..531a9b352 100644
--- a/src/multimedia/effects/effects.pri
+++ b/src/multimedia/effects/effects.pri
@@ -21,7 +21,8 @@ unix:!mac {
}
PUBLIC_HEADERS += \
- effects/qsoundeffect.h
+ effects/qsoundeffect.h \
+ effects/qsound.h
PRIVATE_HEADERS += \
effects/qwavedecoder_p.h \
@@ -30,6 +31,7 @@ PRIVATE_HEADERS += \
SOURCES += \
effects/qsoundeffect.cpp \
effects/qwavedecoder_p.cpp \
- effects/qsamplecache_p.cpp
+ effects/qsamplecache_p.cpp \
+ effects/qsound.cpp
HEADERS +=
diff --git a/src/multimedia/effects/qsound.cpp b/src/multimedia/effects/qsound.cpp
new file mode 100644
index 000000000..3749764ca
--- /dev/null
+++ b/src/multimedia/effects/qsound.cpp
@@ -0,0 +1,236 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsound.h"
+#include "qsoundeffect.h"
+#include "qcoreapplication.h"
+
+
+/*!
+ \class QSound
+ \brief The QSound class provides a way to play .wav sound files.
+
+ \ingroup multimedia
+
+
+ Qt provides the most commonly required audio operation in GUI
+ applications: asynchronously playing a sound file. This is most
+ easily accomplished using the static play() function:
+
+ \snippet doc/src/snippets/multimedia-snippets/qsound.cpp 0
+
+ Alternatively, create a QSound object from the sound file first
+ and then call the play() slot:
+
+ \snippet doc/src/snippets/multimedia-snippets/qsound.cpp 1
+
+ Once created a QSound object can be queried for its fileName() and
+ total number of loops() (i.e. the number of times the sound will
+ play). The number of repetitions can be altered using the
+ setLoops() function. While playing the sound, the loopsRemaining()
+ function returns the remaining number of repetitions. Use the
+ isFinished() function to determine whether the sound has finished
+ playing.
+
+ Sounds played using a QSound object may use more memory than the
+ static play() function, but it may also play more immediately
+ (depending on the underlying platform audio facilities).
+
+*/
+
+
+/*!
+ Plays the sound stored in the file specified by the given \a filename.
+
+ \since 5.0
+ \sa stop(), loopsRemaining(), isFinished()
+*/
+void QSound::play(const QString& filename)
+{
+ // Object destruction is generaly handled via deleteOnComplete
+ // Unexpected cases will be handled via parenting of QSound objects to qApp
+ QSound *sound = new QSound(filename, qApp);
+ sound->connect(sound->m_soundEffect, SIGNAL(playingChanged()), SLOT(deleteOnComplete()));
+ sound->play();
+}
+
+/*!
+ Constructs a QSound object from the file specified by the given \a
+ filename and with the given \a parent.
+
+ \since 5.0
+ \sa play()
+*/
+QSound::QSound(const QString& filename, QObject* parent)
+ : QObject(parent)
+{
+ m_soundEffect = new QSoundEffect(this);
+ m_soundEffect->setSource(QUrl::fromLocalFile(filename));
+}
+
+/*!
+ Destroys this sound object. If the sound is not finished playing,
+ the stop() function is called before the sound object is
+ destroyed.
+
+ \since 5.0
+ \sa stop(), isFinished()
+*/
+QSound::~QSound()
+{
+ if (!isFinished())
+ stop();
+}
+
+/*!
+ Returns true if the sound has finished playing; otherwise returns false.
+*/
+bool QSound::isFinished() const
+{
+ return !m_soundEffect->isPlaying();
+}
+
+/*!
+ \overload
+
+ Starts playing the sound specified by this QSound object.
+
+ The function returns immediately. Depending on the platform audio
+ facilities, other sounds may stop or be mixed with the new
+ sound. The sound can be played again at any time, possibly mixing
+ or replacing previous plays of the sound.
+
+ \since 5.0
+ \sa fileName()
+*/
+void QSound::play()
+{
+ m_soundEffect->play();
+}
+
+/*!
+ Returns the number of times the sound will play.
+ Return value of \c QSound::Infinite indicates infinite number of loops
+
+ \since 5.0
+ \sa loopsRemaining(), setLoops()
+*/
+int QSound::loops() const
+{
+ // retain old API value for infite loops
+ int loopCount = m_soundEffect->loopCount();
+ if (loopCount == QSoundEffect::Infinite)
+ loopCount = Infinite;
+
+ return loopCount;
+}
+
+/*!
+ Returns the remaining number of times the sound will loop (for all
+ positive values this value decreases each time the sound is played).
+ Return value of \c QSound::Infinite indicates infinite number of loops
+
+ \since 5.0
+ \sa loops(), isFinished()
+*/
+int QSound::loopsRemaining() const
+{
+ // retain old API value for infite loops
+ int loopsRemaining = m_soundEffect->loopsRemaining();
+ if (loopsRemaining == QSoundEffect::Infinite)
+ loopsRemaining = Infinite;
+
+ return loopsRemaining;
+}
+
+/*!
+ \fn void QSound::setLoops(int number)
+
+ Sets the sound to repeat the given \a number of times when it is
+ played.
+
+ Note that passing the value \c QSound::Infinite will cause the sound to loop
+ indefinitely.
+
+ \since 5.0
+ \sa loops()
+*/
+void QSound::setLoops(int n)
+{
+ if (n == Infinite)
+ n = QSoundEffect::Infinite;
+
+ m_soundEffect->setLoopCount(n);
+}
+
+/*!
+ Returns the filename associated with this QSound object.
+
+ \since 5.0
+ \sa QSound()
+*/
+QString QSound::fileName() const
+{
+ return m_soundEffect->source().toLocalFile();
+}
+
+/*!
+ Stops the sound playing.
+
+ \since 5.0
+ \sa play()
+*/
+void QSound::stop()
+{
+ m_soundEffect->stop();
+}
+
+/*!
+ \internal
+ \since 5.0
+*/
+void QSound::deleteOnComplete()
+{
+ if (!m_soundEffect->isPlaying())
+ deleteLater();
+}
+
+#include "moc_qsound.cpp"
diff --git a/src/multimedia/effects/qsound.h b/src/multimedia/effects/qsound.h
new file mode 100644
index 000000000..c45ddb10f
--- /dev/null
+++ b/src/multimedia/effects/qsound.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSOUND_H
+#define QSOUND_H
+
+#include <qtmultimediadefs.h>
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Multimedia)
+
+class QSoundEffect;
+
+class Q_MULTIMEDIA_EXPORT QSound : public QObject
+{
+ Q_OBJECT
+public:
+ enum Loop
+ {
+ Infinite = -1,
+ };
+
+ static void play(const QString& filename);
+
+ explicit QSound(const QString& filename, QObject* parent = 0);
+ ~QSound();
+
+ int loops() const;
+ int loopsRemaining() const;
+ void setLoops(int);
+ QString fileName() const;
+
+ bool isFinished() const;
+
+public Q_SLOTS:
+ void play();
+ void stop();
+
+private Q_SLOTS:
+ void deleteOnComplete();
+
+private:
+ QSoundEffect *m_soundEffect;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif // QSOUND_H
diff --git a/src/multimedia/effects/qsoundeffect.cpp b/src/multimedia/effects/qsoundeffect.cpp
index 19021fd0c..b1c359ef0 100644
--- a/src/multimedia/effects/qsoundeffect.cpp
+++ b/src/multimedia/effects/qsoundeffect.cpp
@@ -121,10 +121,17 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \qmlsignal SoundEffect::loopsChanged()
+ \qmlsignal SoundEffect::loopCountChanged()
\since 1.0
- This handler is called when the number of loops has changed.
+ This handler is called when the initial number of loops has changed.
+*/
+
+/*!
+ \qmlsignal SoundEffect::loopsRemainingChanged()
+ \since 1.0
+
+ This handler is called when the remaining number of loops has changed.
*/
/*!
@@ -164,6 +171,7 @@ QSoundEffect::QSoundEffect(QObject *parent) :
QObject(parent)
{
d = new QSoundEffectPrivate(this);
+ connect(d, SIGNAL(loopsRemainingChanged()), SIGNAL(loopsRemainingChanged()));
connect(d, SIGNAL(volumeChanged()), SIGNAL(volumeChanged()));
connect(d, SIGNAL(mutedChanged()), SIGNAL(mutedChanged()));
connect(d, SIGNAL(loadedChanged()), SIGNAL(loadedChanged()));
@@ -201,6 +209,11 @@ int QSoundEffect::loopCount() const
return d->loopCount();
}
+int QSoundEffect::loopsRemaining() const
+{
+ return d->loopsRemaining();
+}
+
void QSoundEffect::setLoopCount(int loopCount)
{
if (loopCount < 0 && loopCount != Infinite) {
diff --git a/src/multimedia/effects/qsoundeffect.h b/src/multimedia/effects/qsoundeffect.h
index bac325d9c..f5df8328e 100644
--- a/src/multimedia/effects/qsoundeffect.h
+++ b/src/multimedia/effects/qsoundeffect.h
@@ -63,6 +63,7 @@ class Q_MULTIMEDIA_EXPORT QSoundEffect : public QObject
Q_CLASSINFO("DefaultMethod", "play()")
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(int loops READ loopCount WRITE setLoopCount NOTIFY loopCountChanged)
+ Q_PROPERTY(int loopsRemaining READ loopsRemaining NOTIFY loopsRemainingChanged)
Q_PROPERTY(qreal volume READ volume WRITE setVolume NOTIFY volumeChanged)
Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged)
Q_PROPERTY(bool playing READ isPlaying NOTIFY playingChanged)
@@ -93,6 +94,7 @@ public:
void setSource(const QUrl &url);
int loopCount() const;
+ int loopsRemaining() const;
void setLoopCount(int loopCount);
qreal volume() const;
@@ -109,6 +111,7 @@ public:
Q_SIGNALS:
void sourceChanged();
void loopCountChanged();
+ void loopsRemainingChanged();
void volumeChanged();
void mutedChanged();
void loadedChanged();
diff --git a/src/multimedia/effects/qsoundeffect_pulse_p.cpp b/src/multimedia/effects/qsoundeffect_pulse_p.cpp
index aa88f4c4b..373586ef5 100644
--- a/src/multimedia/effects/qsoundeffect_pulse_p.cpp
+++ b/src/multimedia/effects/qsoundeffect_pulse_p.cpp
@@ -410,7 +410,7 @@ void QSoundEffectPrivate::setSource(const QUrl &url)
m_sampleReady = false;
PulseDaemonLocker locker;
- m_runningCount = 0;
+ setLoopsRemaining(0);
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);
@@ -444,6 +444,11 @@ int QSoundEffectPrivate::loopCount() const
return m_loopCount;
}
+int QSoundEffectPrivate::loopsRemaining() const
+{
+ return m_runningCount;
+}
+
void QSoundEffectPrivate::setLoopCount(int loopCount)
{
if (loopCount == 0)
@@ -542,6 +547,17 @@ void QSoundEffectPrivate::setStatus(QSoundEffect::Status status)
emit loadedChanged();
}
+void QSoundEffectPrivate::setLoopsRemaining(int loopsRemaining)
+{
+#ifdef QT_PA_DEBUG
+ qDebug() << this << "setLoopsRemaining " << loopsRemaining;
+#endif
+ if (m_runningCount == loopsRemaining)
+ return;
+ m_runningCount = loopsRemaining;
+ emit loopsRemainingChanged();
+}
+
void QSoundEffectPrivate::play()
{
#ifdef QT_PA_DEBUG
@@ -561,7 +577,7 @@ void QSoundEffectPrivate::play()
#ifdef QT_PA_DEBUG
qDebug() << this << "restart playing";
#endif
- m_runningCount = 0;
+ setLoopsRemaining(0);
m_playQueued = true;
Q_ASSERT(m_pulseStream);
emptyStream();
@@ -708,7 +724,7 @@ void QSoundEffectPrivate::prepare()
}
if (m_playQueued) {
m_playQueued = false;
- m_runningCount = m_loopCount;
+ setLoopsRemaining(m_loopCount);
playSample();
}
}
@@ -727,7 +743,7 @@ void QSoundEffectPrivate::uploadSample()
if (m_position == m_sample->data().size()) {
m_position = 0;
if (m_runningCount > 0)
- m_runningCount--;
+ setLoopsRemaining(m_runningCount - 1);
if (m_runningCount == 0) {
return;
}
@@ -745,7 +761,7 @@ void QSoundEffectPrivate::uploadSample()
if (m_position == m_sample->data().size()) {
m_position = 0;
if (m_runningCount > 0)
- m_runningCount--;
+ setLoopsRemaining(m_runningCount - 1);
if (m_runningCount != 0 && firstPartLength < writableSize)
{
while (writtenBytes < writableSize) {
@@ -760,7 +776,7 @@ void QSoundEffectPrivate::uploadSample()
break;
}
if (m_runningCount > 0)
- m_runningCount--;
+ setLoopsRemaining(m_runningCount - 1);
if (m_runningCount == 0)
break;
}
@@ -793,7 +809,7 @@ void QSoundEffectPrivate::stop()
m_stopping = true;
if (m_pulseStream)
emptyStream();
- m_runningCount = 0;
+ setLoopsRemaining(0);
m_position = 0;
m_playQueued = false;
}
diff --git a/src/multimedia/effects/qsoundeffect_pulse_p.h b/src/multimedia/effects/qsoundeffect_pulse_p.h
index 3992617ba..35b586e8d 100644
--- a/src/multimedia/effects/qsoundeffect_pulse_p.h
+++ b/src/multimedia/effects/qsoundeffect_pulse_p.h
@@ -82,6 +82,7 @@ public:
QUrl source() const;
void setSource(const QUrl &url);
int loopCount() const;
+ int loopsRemaining() const;
void setLoopCount(int loopCount);
int volume() const;
void setVolume(int volume);
@@ -98,6 +99,7 @@ public Q_SLOTS:
void stop();
Q_SIGNALS:
+ void loopsRemainingChanged();
void volumeChanged();
void mutedChanged();
void loadedChanged();
@@ -125,6 +127,7 @@ private:
void setPlaying(bool playing);
void setStatus(QSoundEffect::Status status);
+ void setLoopsRemaining(int loopsRemaining);
static void stream_write_callback(pa_stream *s, size_t length, void *userdata);
static void stream_state_callback(pa_stream *s, void *userdata);
diff --git a/src/multimedia/effects/qsoundeffect_qmedia_p.cpp b/src/multimedia/effects/qsoundeffect_qmedia_p.cpp
index 7ae785cd9..511aa06b5 100644
--- a/src/multimedia/effects/qsoundeffect_qmedia_p.cpp
+++ b/src/multimedia/effects/qsoundeffect_qmedia_p.cpp
@@ -105,6 +105,11 @@ int QSoundEffectPrivate::loopCount() const
return m_loopCount;
}
+int QSoundEffectPrivate::loopsRemaining() const
+{
+ return m_runningCount;
+}
+
void QSoundEffectPrivate::setLoopCount(int loopCount)
{
m_loopCount = loopCount;
@@ -150,19 +155,19 @@ void QSoundEffectPrivate::play()
if (m_status == QSoundEffect::Null || m_status == QSoundEffect::Error)
return;
if (m_loopCount < 0) {
- m_runningCount = -1;
+ setLoopsRemaining(-1);
}
else {
if (m_runningCount < 0)
- m_runningCount = 0;
- m_runningCount += m_loopCount;
+ setLoopsRemaining(0);
+ setLoopsRemaining(m_runningCount + m_loopCount);
}
m_player->play();
}
void QSoundEffectPrivate::stop()
{
- m_runningCount = 0;
+ setLoopsRemaining(0);
m_player->stop();
}
@@ -174,10 +179,13 @@ void QSoundEffectPrivate::stateChanged(QMediaPlayer::State state)
} else if (m_runningCount == 0) {
setPlaying(false);
return;
- } else if (--m_runningCount > 0) {
- m_player->play();
} else {
- setPlaying(false);
+ setLoopsRemaining(m_runningCount - 1);
+ if (m_runningCount > 0) {
+ m_player->play();
+ } else {
+ setPlaying(false);
+ }
}
} else {
setPlaying(true);
@@ -233,6 +241,14 @@ void QSoundEffectPrivate::setPlaying(bool playing)
emit playingChanged();
}
+void QSoundEffectPrivate::setLoopsRemaining(int loopsRemaining)
+{
+ if (m_runningCount == loopsRemaining)
+ return;
+ m_runningCount = loopsRemaining;
+ emit loopsRemainingChanged();
+}
+
QT_END_NAMESPACE
#include "moc_qsoundeffect_qmedia_p.cpp"
diff --git a/src/multimedia/effects/qsoundeffect_qmedia_p.h b/src/multimedia/effects/qsoundeffect_qmedia_p.h
index b93f47ce3..bb91e50b0 100644
--- a/src/multimedia/effects/qsoundeffect_qmedia_p.h
+++ b/src/multimedia/effects/qsoundeffect_qmedia_p.h
@@ -79,6 +79,7 @@ public:
QUrl source() const;
void setSource(const QUrl &url);
int loopCount() const;
+ int loopsRemaining() const;
void setLoopCount(int loopCount);
int volume() const;
void setVolume(int volume);
@@ -95,6 +96,7 @@ public Q_SLOTS:
void stop();
Q_SIGNALS:
+ void loopsRemainingChanged();
void volumeChanged();
void mutedChanged();
void loadedChanged();
@@ -109,6 +111,7 @@ private Q_SLOTS:
private:
void setStatus(QSoundEffect::Status status);
void setPlaying(bool playing);
+ void setLoopsRemaining(int loopsRemaining);
int m_loopCount;
int m_runningCount;