--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 <AL/al.h>
+
+int main(int argc, char** argv)
+{
+ return 0;
+}
--- /dev/null
+TEMPLATE = app
+DEPENDPATH += .
+INCLUDEPATH += .
+
+SOURCES += main.cpp
+
+win32 {
+ LIBS += -lOpenAL32
+}else {
+ LIBS += -lopenal
+}
--- /dev/null
+TEMPLATE = subdirs
+
+# These examples contain no C++ and can simply be copied
+SUBDIRS =
+sources.files = qml/*
+sources.path = $$[QT_INSTALL_EXAMPLES]/qtmultimedia/declarative/audioengine
+INSTALLS += sources
--- /dev/null
+/****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the examples of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:BSD$
+ ** You may use this file under the terms of the BSD license as follows:
+ **
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ ** * Redistributions of source code must retain the above copyright
+ ** notice, this list of conditions and the following disclaimer.
+ ** * Redistributions in binary form must reproduce the above copyright
+ ** notice, this list of conditions and the following disclaimer in
+ ** the documentation and/or other materials provided with the
+ ** distribution.
+ ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+ ** the names of its contributors may be used to endorse or promote
+ ** products derived from this software without specific prior written
+ ** permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+import QtAudioEngine 1.0
+import QtQuick 2.0
+import "content"
+
+Rectangle {
+ color:"white"
+ id: root
+ width: 300
+ height: 500
+ property int radius : 100
+ property real twoPi : Math.PI + Math.PI
+
+ MyAudioEngine {
+ id:audioEngine
+ listener.position : Qt.vector3d(observer.x, observer.y, 0);
+ }
+
+ Item {
+ id: circle
+ x: root.width / 2
+ y: root.height / 2
+ property real percent: 0
+ SequentialAnimation on percent {
+ id: circleAnim1
+ loops: Animation.Infinite
+ running: true
+ NumberAnimation {
+ duration: 8000
+ from: 0
+ to: 1
+ }
+
+ }
+ }
+
+ Item {
+ id: holder
+ x: circle.x - Math.sin(circle.percent * root.twoPi) * root.radius - 50
+ y: circle.y + Math.cos(circle.percent * root.twoPi) * root.radius + 50
+ }
+
+ Rectangle {
+ color:"green"
+ id: observer
+ width: 16
+ height: 16
+ x: circle.x - width / 2
+ y: circle.y - height / 2
+ }
+ Rectangle {
+ color:"red"
+ id: starship
+ width: 32
+ height: 32
+ x: holder.x - width / 2
+ y: holder.y - height / 2
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ audioEngine.sounds["effects"].play(Qt.vector3d(holder.x, holder.y, 0));
+ }
+ }
+
+ SoundInstance {
+ id: shipSound
+ engine:audioEngine
+ sound:"shipengine"
+ position: Qt.vector3d(holder.x, holder.y, 0)
+ direction: {
+ var a = (starship.rotation / 360) * root.twoPi;
+ return Qt.vector3d(Math.sin(a), -Math.cos(a), 0);
+ }
+ velocity: {
+ var speed = root.twoPi * root.radius / 4;
+ return shipSound.direction * speed;
+ }
+
+ Component.onCompleted: shipSound.play()
+ }
+
+ //Category Volume Control
+ Rectangle {
+ property variant volumeCtrl: audioEngine.categories["sfx"];
+ id: volumeBar
+ x: 10
+ y: 10
+ width: 280
+ height: 22
+ color: "darkgray"
+ Rectangle {
+ id: volumeTracker
+ x: 0
+ y: 0
+ width: volumeBar.volumeCtrl.volume * parent.width;
+ height: parent.height
+ color: "lightgreen"
+ }
+ Text {
+ text: " volume:" + volumeBar.volumeCtrl.volume * 100 +"%";
+ font.pointSize: 16;
+ font.italic: true;
+ color: "black"
+ anchors.fill: parent
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ property bool m:false
+ onPressed: {
+ m = true;
+ updateVolume(mouse);
+ }
+ onReleased: {
+ m = false;
+ }
+
+ onPositionChanged: {
+ if (m) {
+ updateVolume(mouse);
+ }
+ }
+ function updateVolume(mouse) {
+ volumeBar.volumeCtrl.volume = Math.min(1, Math.max(0, mouse.x / (volumeBar.width - 1)));
+ }
+ }
+ }
+
+ //Information display
+ Item {
+ x:10
+ y:32
+ Text {
+ text: " [live instances] = " + audioEngine.liveInstances;
+ font.pointSize: 14;
+ font.italic: true;
+ color: "black"
+ anchors.fill: parent
+ }
+ }
+
+ Item {
+ x:10
+ y:60
+ Text {
+ text: " [loading]=" + (audioEngine.loading ? "true" : "false");
+ font.pointSize: 16;
+ font.italic: true;
+ color: "black"
+ anchors.fill: parent
+ }
+ }
+}
--- /dev/null
+import QmlProject 1.1
+
+Project {
+ mainFile: "audioengine.qml"
+
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+ QmlFiles {
+ directory: "."
+ }
+ JavaScriptFiles {
+ directory: "."
+ }
+ ImageFiles {
+ directory: "."
+ }
+}
--- /dev/null
+/****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the examples of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:BSD$
+ ** You may use this file under the terms of the BSD license as follows:
+ **
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ ** * Redistributions of source code must retain the above copyright
+ ** notice, this list of conditions and the following disclaimer.
+ ** * Redistributions in binary form must reproduce the above copyright
+ ** notice, this list of conditions and the following disclaimer in
+ ** the documentation and/or other materials provided with the
+ ** distribution.
+ ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+ ** the names of its contributors may be used to endorse or promote
+ ** products derived from this software without specific prior written
+ ** permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+import QtAudioEngine 1.0
+import QtQuick 2.0
+
+AudioEngine {
+
+ AudioCategory {
+ name:"sfx"
+ volume: 1
+ }
+
+ AudioCategory {
+ name:"music"
+ volume: 1
+ }
+
+
+ AttenuationModelInverse {
+ name:"default"
+ start: 20
+ end: 1000
+ rolloff: 1
+ }
+
+ AttenuationModelLinear {
+ name:"shipengine"
+ start: 20
+ end: 180
+ }
+
+ AudioSample {
+ name:"fire"
+ source: "fire-03-loop.wav"
+ preloaded:true
+ }
+
+ AudioSample {
+ name:"explosion"
+ source: "explosion-02.wav"
+ }
+ AudioSample {
+ name:"lava"
+ source: "lava-bubbling-01.wav"
+ }
+ AudioSample {
+ name:"water"
+ source: "running-water-01.wav"
+ }
+ Sound {
+ name:"shipengine"
+ attenuationModel:"shipengine"
+ category:"sfx"
+ PlayVariation {
+ looping:true
+ sample:"fire"
+ maxGain:0.9
+ minGain:0.8
+ }
+ }
+
+ Sound {
+ name:"effects"
+ category:"sfx"
+ PlayVariation {
+ sample:"lava"
+ maxGain:1.5
+ minGain:1.2
+ maxPitch:2.0
+ minPitch:0.5
+ }
+ PlayVariation {
+ sample:"explosion"
+ maxGain:1.1
+ minGain:0.7
+ maxPitch:1.5
+ minPitch:0.5
+ }
+ PlayVariation {
+ sample:"water"
+ maxGain:1.5
+ minGain:1.2
+ }
+ }
+
+ dopplerFactor: 1
+ speedOfSound: 343.33
+
+ listener.up:"0,0,1"
+ listener.position:"0,0,0"
+ listener.velocity:"0,0,0"
+ listener.direction:"0,1,0"
+}
QT += widgets
}
+contains(config_test_openal, yes): SUBDIRS += audioengine
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 <QtDeclarative/qdeclarativeextensionplugin.h>
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+
+#include "qdeclarative_audioengine_p.h"
+#include "qdeclarative_soundinstance_p.h"
+#include "qdeclarative_sound_p.h"
+#include "qdeclarative_playvariation_p.h"
+#include "qdeclarative_audiocategory_p.h"
+#include "qdeclarative_audiolistener_p.h"
+#include "qdeclarative_audiosample_p.h"
+#include "qdeclarative_attenuationmodel_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QAudioEngineDeclarativeModule : public QDeclarativeExtensionPlugin
+{
+ Q_OBJECT
+public:
+ virtual void registerTypes(const char *uri)
+ {
+ Q_ASSERT(QLatin1String(uri) == QLatin1String("QtAudioEngine"));
+
+ qmlRegisterType<QDeclarativeAudioEngine>(uri, 1, 0, "AudioEngine");
+ qmlRegisterType<QDeclarativeAudioSample>(uri, 1, 0, "AudioSample");
+ qmlRegisterType<QDeclarativeAudioCategory>(uri, 1, 0, "AudioCategory");
+ qmlRegisterType<QDeclarativeSoundCone>(uri, 1, 0, "");
+ qmlRegisterType<QDeclarativeSound>(uri, 1, 0, "Sound");
+ qmlRegisterType<QDeclarativePlayVariation>(uri, 1, 0, "PlayVariation");
+ qmlRegisterType<QDeclarativeAudioListener>(uri, 1, 0, "AudioListener");
+ qmlRegisterType<QDeclarativeSoundInstance>(uri, 1, 0, "SoundInstance");
+
+ qmlRegisterType<QDeclarativeAttenuationModelLinear>(uri, 1, 0, "AttenuationModelLinear");
+ qmlRegisterType<QDeclarativeAttenuationModelInverse>(uri, 1, 0, "AttenuationModelInverse");
+ }
+};
+
+QT_END_NAMESPACE
+
+#include "audioengine.moc"
+
+Q_EXPORT_PLUGIN2("QtAudioEngine", QT_PREPEND_NAMESPACE(QAudioEngineDeclarativeModule));
+
--- /dev/null
+TARGET = declarative_audioengine
+TARGETPATH = QtAudioEngine
+
+include(../qimportbase.pri)
+QT += declarative quick multimedia-private
+
+win32 {
+ LIBS += -lOpenAL32
+}else {
+ LIBS += -lopenal
+}
+
+DESTDIR = $$QT.multimedia.imports/$$TARGETPATH
+target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
+
+INCLUDEPATH += ../../multimedia/audio
+
+HEADERS += \
+ qdeclarative_attenuationmodel_p.h \
+ qdeclarative_audioengine_p.h \
+ qdeclarative_soundinstance_p.h \
+ qdeclarative_audiocategory_p.h \
+ qdeclarative_audiolistener_p.h \
+ qdeclarative_playvariation_p.h \
+ qdeclarative_audiosample_p.h \
+ qdeclarative_sound_p.h \
+ qsoundinstance_p.h \
+ qaudioengine_p.h \
+ qsoundsource_p.h \
+ qsoundbuffer_p.h \
+ qaudioengine_openal_p.h
+
+SOURCES += \
+ audioengine.cpp \
+ qdeclarative_attenuationmodel_p.cpp \
+ qdeclarative_audioengine_p.cpp \
+ qdeclarative_soundinstance_p.cpp \
+ qdeclarative_audiocategory_p.cpp \
+ qdeclarative_audiolistener_p.cpp \
+ qdeclarative_playvariation_p.cpp \
+ qdeclarative_audiosample_p.cpp \
+ qdeclarative_sound_p.cpp \
+ qsoundinstance_p.cpp \
+ qaudioengine_p.cpp \
+ qsoundsource_openal_p.cpp \
+ qaudioengine_openal_p.cpp
+
+qmldir.files += $$PWD/qmldir
+qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
+
+INSTALLS += target qmldir
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 <QtCore/QThread>
+#include <QtNetwork/QNetworkRequest>
+#include <QtNetwork/QNetworkReply>
+#include <QtNetwork/QNetworkAccessManager>
+#include <QtCore/QUrl>
+#include <QtCore/QThread>
+#include <QtCore/QMutex>
+
+#include "qsamplecache_p.h"
+#include "qaudioengine_openal_p.h"
+
+#include "qdebug.h"
+
+#define DEBUG_AUDIOENGINE
+
+QT_USE_NAMESPACE
+
+class StaticSoundBufferAL : public QSoundBufferPrivateAL
+{
+ Q_OBJECT
+public:
+ StaticSoundBufferAL(QObject *parent, const QUrl& url, QSampleCache *sampleLoader)
+ : QSoundBufferPrivateAL(parent)
+ , m_ref(1)
+ , m_url(url)
+ , m_alBuffer(0)
+ , m_isReady(false)
+ , m_sample(0)
+ , m_sampleLoader(sampleLoader)
+ {
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "creating new StaticSoundBufferOpenAL";
+#endif
+ }
+
+ void load()
+ {
+ if (m_sample)
+ return;
+ m_sample = m_sampleLoader->requestSample(m_url);
+ connect(m_sample, SIGNAL(error()), this, SLOT(decoderError()));
+ connect(m_sample, SIGNAL(ready()), this, SLOT(sampleReady()));
+ switch (m_sample->state()) {
+ case QSample::Ready:
+ sampleReady();
+ break;
+ case QSample::Error:
+ decoderError();
+ break;
+ default:
+ break;
+ }
+ }
+
+ ~StaticSoundBufferAL()
+ {
+ if (m_sample)
+ m_sample->release();
+ alDeleteBuffers(1, &m_alBuffer);
+ }
+
+ void bindToSource(ALuint alSource)
+ {
+ Q_ASSERT(m_alBuffer != 0);
+ alSourcei(alSource, AL_BUFFER, m_alBuffer);
+ }
+
+ void unbindFromSource(ALuint alSource)
+ {
+ alSourcei(alSource, AL_BUFFER, 0);
+ }
+
+ //called in application
+ bool isReady() const
+ {
+ return m_isReady;
+ }
+
+ long addRef()
+ {
+ return ++m_ref;
+ }
+
+ long release()
+ {
+ return --m_ref;
+ }
+
+ long refCount() const
+ {
+ return m_ref;
+ }
+
+public Q_SLOTS:
+ void sampleReady()
+ {
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "StaticSoundBufferOpenAL:sample[" << m_url << "] loaded";
+#endif
+
+ disconnect(m_sample, SIGNAL(error()), this, SLOT(decoderError()));
+ disconnect(m_sample, SIGNAL(ready()), this, SLOT(sampleReady()));
+
+ if (m_sample->data().size() > 1024 * 1024 * 4) {
+ qWarning() << "source [" << m_url << "] size too large!";
+ decoderError();
+ return;
+ }
+
+ if (m_sample->format().channelCount() > 2) {
+ qWarning() << "source [" << m_url << "] channel > 2!";
+ decoderError();
+ return;
+ }
+
+ ALenum alFormat = 0;
+ if (m_sample->format().sampleSize() == 8) {
+ alFormat = m_sample->format().channelCount() == 1 ? AL_FORMAT_MONO8 : AL_FORMAT_STEREO8;
+ } else if (m_sample->format().sampleSize() == 16) {
+ alFormat = m_sample->format().channelCount() == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
+ } else {
+ qWarning() << "source [" << m_url << "] invalid sample size:"
+ << m_sample->format().sampleSize() << "(should be 8 or 16)";
+ decoderError();
+ return;
+ }
+
+ alGenBuffers(1, &m_alBuffer);
+ if (!QAudioEnginePrivate::checkNoError("create buffer")) {
+ return;
+ }
+ alBufferData(m_alBuffer, alFormat, m_sample->data().data(),
+ m_sample->data().size(), m_sample->format().frequency());
+
+ if (!QAudioEnginePrivate::checkNoError("fill buffer")) {
+ return;
+ }
+ m_isReady = true;
+ emit ready();
+
+ m_sample->release();
+ m_sample = 0;
+ }
+
+ void decoderError()
+ {
+ qWarning() << "loading [" << m_url << "] failed";
+ disconnect(m_sample, SIGNAL(error()), this, SLOT(decoderError()));
+ emit error();
+ }
+
+private:
+ long m_ref;
+ QUrl m_url;
+ ALuint m_alBuffer;
+ bool m_isReady;
+ QSample *m_sample;
+ QSampleCache *m_sampleLoader;
+};
+
+QSoundBufferPrivateAL::QSoundBufferPrivateAL(QObject *parent)
+ : QSoundBuffer(parent)
+{
+}
+
+
+/////////////////////////////////////////////////////////////////
+QAudioEnginePrivate::QAudioEnginePrivate(QObject *parent)
+ : QObject(parent)
+{
+ m_updateTimer.setInterval(200);
+ connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateSoundSources()));
+
+ m_sampleLoader = new QSampleCache(this);
+ m_sampleLoader->setCapacity(0);
+ connect(m_sampleLoader, SIGNAL(isLoadingChanged()), this, SIGNAL(isLoadingChanged()));
+
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "default openal device = " << alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
+
+ const ALCchar* devNames = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
+ int cc = 0;
+ qDebug() << "device list:";
+ while (true) {
+ qDebug() << " " << devNames + cc;
+ while (devNames[cc] != 0)
+ ++cc;
+ ++cc;
+ if (devNames[cc] == 0)
+ break;
+ }
+#endif
+
+ ALCdevice *device = alcOpenDevice(0);
+ if (!device) {
+ qWarning() << "Can not create openal device!";
+ return;
+ }
+
+ ALCcontext* context = alcCreateContext(device, 0);
+ if (!context) {
+ qWarning() << "Can not create openal context!";
+ return;
+ }
+ alcMakeContextCurrent(context);
+ alDistanceModel(AL_NONE);
+ alDopplerFactor(0);
+}
+
+QAudioEnginePrivate::~QAudioEnginePrivate()
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QAudioEnginePrivate::dtor";
+#endif
+ delete m_sampleLoader;
+ QObjectList children = this->children();
+ foreach (QObject *child, children) {
+ QSoundSourcePrivate* s = qobject_cast<QSoundSourcePrivate*>(child);
+ if (!s)
+ continue;
+ s->release();
+ }
+
+ foreach (QSoundBufferPrivateAL *buffer, m_staticBufferPool) {
+ delete buffer;
+ }
+ m_staticBufferPool.clear();
+
+ ALCcontext* context = alcGetCurrentContext();
+ ALCdevice *device = alcGetContextsDevice(context);
+ alcDestroyContext(context);
+ alcCloseDevice(device);
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QAudioEnginePrivate::dtor: all done";
+#endif
+}
+
+bool QAudioEnginePrivate::isLoading() const
+{
+ return m_sampleLoader->isLoading();
+}
+
+QSoundSource* QAudioEnginePrivate::createSoundSource()
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QAudioEnginePrivate::createSoundSource()";
+#endif
+ QSoundSourcePrivate *instance = NULL;
+ if (m_instancePool.count() == 0) {
+ instance = new QSoundSourcePrivate(this);
+ } else {
+ instance = m_instancePool.front();
+ m_instancePool.pop_front();
+ }
+ connect(instance, SIGNAL(activate(QObject*)), this, SLOT(soundSourceActivate(QObject*)));
+ return instance;
+}
+
+void QAudioEnginePrivate::releaseSoundSource(QSoundSource *soundInstance)
+{
+ QSoundSourcePrivate *privInstance = static_cast<QSoundSourcePrivate*>(soundInstance);
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "recycle soundInstance" << privInstance;
+#endif
+ privInstance->unbindBuffer();
+ m_instancePool.push_front(privInstance);
+ m_activeInstances.removeOne(privInstance);
+}
+
+QSoundBuffer* QAudioEnginePrivate::getStaticSoundBuffer(const QUrl& url)
+{
+ StaticSoundBufferAL *staticBuffer = NULL;
+ QMap<QUrl, QSoundBufferPrivateAL*>::iterator it = m_staticBufferPool.find(url);
+ if (it == m_staticBufferPool.end()) {
+ staticBuffer = new StaticSoundBufferAL(this, url, m_sampleLoader);
+ m_staticBufferPool.insert(url, staticBuffer);
+ } else {
+ staticBuffer = static_cast<StaticSoundBufferAL*>(*it);
+ staticBuffer->addRef();
+ }
+ return staticBuffer;
+}
+
+void QAudioEnginePrivate::releaseSoundBuffer(QSoundBuffer *buffer)
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QAudioEnginePrivate: recycle sound buffer";
+#endif
+ if (buffer->inherits("StaticSoundBufferOpenAL")) {
+ StaticSoundBufferAL *staticBuffer = static_cast<StaticSoundBufferAL*>(buffer);
+ //decrement the reference count, still kept in memory for reuse
+ staticBuffer->release();
+ //TODO implement some resource recycle strategy
+ } else {
+ //TODO
+ Q_ASSERT(0);
+ qWarning() << "Unknown soundbuffer type for recycle" << buffer;
+ }
+}
+
+bool QAudioEnginePrivate::checkNoError(const char *msg)
+{
+ ALenum error = alGetError();
+ if (error != AL_NO_ERROR) {
+ qWarning() << "Failed on" << msg << "[OpenAL error code =" << error << "]";
+ return false;
+ }
+ return true;
+}
+
+QVector3D QAudioEnginePrivate::listenerPosition() const
+{
+ ALfloat x, y, z;
+ alGetListener3f(AL_POSITION, &x, &y, &z);
+ checkNoError("get listener position");
+ return QVector3D(x, y, z);
+}
+
+QVector3D QAudioEnginePrivate::listenerVelocity() const
+{
+ ALfloat x, y, z;
+ alGetListener3f(AL_VELOCITY, &x, &y, &z);
+ checkNoError("get listener velocity");
+ return QVector3D(x, y, z);
+}
+
+qreal QAudioEnginePrivate::listenerGain() const
+{
+ ALfloat gain;
+ alGetListenerf(AL_GAIN, &gain);
+ checkNoError("get listener gain");
+ return gain;
+}
+
+void QAudioEnginePrivate::setListenerPosition(const QVector3D& position)
+{
+ alListener3f(AL_POSITION, position.x(), position.y(), position.z());
+ checkNoError("set listener position");
+}
+
+void QAudioEnginePrivate::setListenerOrientation(const QVector3D& direction, const QVector3D& up)
+{
+ ALfloat orientation[6];
+ orientation[0] = direction.x();
+ orientation[1] = direction.y();
+ orientation[2] = direction.z();
+ orientation[3] = up.x();
+ orientation[4] = up.y();
+ orientation[5] = up.z();
+ alListenerfv(AL_ORIENTATION, orientation);
+ checkNoError("set listener orientation");
+}
+
+void QAudioEnginePrivate::setListenerVelocity(const QVector3D& velocity)
+{
+ alListener3f(AL_VELOCITY, velocity.x(), velocity.y(), velocity.z());
+ checkNoError("set listener velocity");
+}
+
+void QAudioEnginePrivate::setListenerGain(qreal gain)
+{
+ alListenerf(AL_GAIN, gain);
+ checkNoError("set listener gain");
+}
+
+void QAudioEnginePrivate::setDopplerFactor(qreal dopplerFactor)
+{
+ alDopplerFactor(dopplerFactor);
+}
+
+void QAudioEnginePrivate::setSpeedOfSound(qreal speedOfSound)
+{
+ alSpeedOfSound(speedOfSound);
+}
+
+void QAudioEnginePrivate::soundSourceActivate(QObject *soundSource)
+{
+ QSoundSourcePrivate *ss = qobject_cast<QSoundSourcePrivate*>(soundSource);
+ ss->checkState();
+ if (ss->isLooping())
+ return;
+ if (!m_activeInstances.contains(ss))
+ m_activeInstances.push_back(ss);
+ if (!m_updateTimer.isActive())
+ m_updateTimer.start();
+}
+
+void QAudioEnginePrivate::updateSoundSources()
+{
+ for (QList<QSoundSourcePrivate*>::Iterator it = m_activeInstances.begin();
+ it != m_activeInstances.end();) {
+ QSoundSourcePrivate *instance = *it;
+ instance->checkState();
+ if (instance->state() == QSoundSource::StoppedState) {
+ it = m_activeInstances.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ if (m_activeInstances.count() == 0) {
+ m_updateTimer.stop();
+ }
+}
+
+#include "qaudioengine_openal_p.moc"
+//#include "moc_qaudioengine_openal_p.cpp"
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 QAUDIOENGINE_OPENAL_P_H
+#define QAUDIOENGINE_OPENAL_P_H
+
+#include <QObject>
+#include <QList>
+#include <QMap>
+#include <QTimer>
+
+#include <AL/al.h>
+#include <AL/alc.h>
+
+#include "qsoundsource_p.h"
+#include "qsoundbuffer_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSoundBufferPrivateAL : public QSoundBuffer
+{
+ Q_OBJECT
+public:
+ QSoundBufferPrivateAL(QObject* parent);
+ virtual void bindToSource(ALuint alSource) = 0;
+ virtual void unbindFromSource(ALuint alSource) = 0;
+};
+
+class QSoundSourcePrivate : public QSoundSource
+{
+ Q_OBJECT
+public:
+ QSoundSourcePrivate(QObject *parent);
+ ~QSoundSourcePrivate();
+
+ void play();
+ void pause();
+ void stop();
+
+ QSoundSource::State state() const;
+
+ bool isLooping() const;
+ void setLooping(bool looping);
+ void setPosition(const QVector3D& position);
+ void setDirection(const QVector3D& direction);
+ void setVelocity(const QVector3D& velocity);
+
+ QVector3D velocity() const;
+ QVector3D position() const;
+ QVector3D direction() const;
+
+ void setGain(qreal gain);
+ void setPitch(qreal pitch);
+ void setCone(qreal innerAngle, qreal outerAngle, qreal outerGain);
+
+ void bindBuffer(QSoundBuffer*);
+ void unbindBuffer();
+
+ void checkState();
+
+ void release();
+
+Q_SIGNALS:
+ void activate(QObject*);
+
+private:
+ void sourcePlay();
+ void sourcePause();
+
+ ALuint m_alSource;
+ QSoundBufferPrivateAL *m_bindBuffer;
+ bool m_isReady; //true if the sound source is already bound to some sound buffer
+ QSoundSource::State m_state;
+ qreal m_gain;
+ qreal m_pitch;
+ qreal m_coneInnerAngle;
+ qreal m_coneOuterAngle;
+ qreal m_coneOuterGain;
+};
+
+class QSampleCache;
+class QAudioEnginePrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QAudioEnginePrivate(QObject *parent);
+ ~QAudioEnginePrivate();
+
+ bool isLoading() const;
+
+ QSoundSource* createSoundSource();
+ void releaseSoundSource(QSoundSource *soundInstance);
+ QSoundBuffer* getStaticSoundBuffer(const QUrl& url);
+ void releaseSoundBuffer(QSoundBuffer *buffer);
+
+ QVector3D listenerPosition() const;
+ QVector3D listenerVelocity() const;
+ qreal listenerGain() const;
+ void setListenerPosition(const QVector3D& position);
+ void setListenerVelocity(const QVector3D& velocity);
+ void setListenerOrientation(const QVector3D& direction, const QVector3D& up);
+ void setListenerGain(qreal gain);
+ void setDopplerFactor(qreal dopplerFactor);
+ void setSpeedOfSound(qreal speedOfSound);
+
+ static bool checkNoError(const char *msg);
+
+Q_SIGNALS:
+ void isLoadingChanged();
+
+private Q_SLOTS:
+ void updateSoundSources();
+ void soundSourceActivate(QObject *soundSource);
+
+private:
+ QList<QSoundSourcePrivate*> m_activeInstances;
+ QList<QSoundSourcePrivate*> m_instancePool;
+ QMap<QUrl, QSoundBufferPrivateAL*> m_staticBufferPool;
+
+ QSampleCache *m_sampleLoader;
+ QTimer m_updateTimer;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 "qaudioengine_p.h"
+#include "qsoundsource_p.h"
+#include "qdebug.h"
+
+#include "qaudioengine_openal_p.h"
+
+#define DEBUG_AUDIOENGINE
+
+QT_USE_NAMESPACE
+
+QSoundSource::QSoundSource(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QSoundBuffer::QSoundBuffer(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QAudioEngine* QAudioEngine::create(QObject *parent)
+{
+ return new QAudioEngine(parent);
+}
+
+QAudioEngine::QAudioEngine(QObject *parent)
+ : QObject(parent)
+ , m_listenerUp(0, 0, 1)
+ , m_listenerDirection(0, 1, 0)
+{
+ d = new QAudioEnginePrivate(this);
+ connect(d, SIGNAL(isLoadingChanged()), this, SIGNAL(isLoadingChanged()));
+ setDopplerFactor(1);
+ setSpeedOfSound(qreal(343.33));
+ updateListenerOrientation();
+}
+
+QAudioEngine::~QAudioEngine()
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QAudioEngine::dtor";
+#endif
+}
+
+QSoundBuffer* QAudioEngine::getStaticSoundBuffer(const QUrl& url)
+{
+ return d->getStaticSoundBuffer(url);
+}
+
+void QAudioEngine::releaseSoundBuffer(QSoundBuffer *buffer)
+{
+ d->releaseSoundBuffer(buffer);
+}
+
+QSoundSource* QAudioEngine::createSoundSource()
+{
+ return d->createSoundSource();
+}
+
+void QAudioEngine::releaseSoundSource(QSoundSource *soundInstance)
+{
+ d->releaseSoundSource(soundInstance);
+}
+
+bool QAudioEngine::isLoading() const
+{
+ return d->isLoading();
+}
+
+QVector3D QAudioEngine::listenerPosition() const
+{
+ return d->listenerPosition();
+}
+
+QVector3D QAudioEngine::listenerDirection() const
+{
+ return m_listenerDirection;
+}
+
+QVector3D QAudioEngine::listenerUp() const
+{
+ return m_listenerUp;
+}
+
+qreal QAudioEngine::listenerGain() const
+{
+ return d->listenerGain();
+}
+
+QVector3D QAudioEngine::listenerVelocity() const
+{
+ return d->listenerVelocity();
+}
+
+void QAudioEngine::setListenerPosition(const QVector3D& position)
+{
+ d->setListenerPosition(position);
+}
+
+void QAudioEngine::setListenerVelocity(const QVector3D& velocity)
+{
+ d->setListenerVelocity(velocity);
+}
+
+void QAudioEngine::setListenerDirection(const QVector3D& direction)
+{
+ if (m_listenerDirection == direction)
+ return;
+ m_listenerDirection = direction;
+ updateListenerOrientation();
+}
+
+void QAudioEngine::setListenerUp(const QVector3D& up)
+{
+ if (m_listenerUp == up)
+ return;
+ m_listenerUp = up;
+ updateListenerOrientation();
+}
+
+void QAudioEngine::updateListenerOrientation()
+{
+ QVector3D dir = m_listenerDirection;
+ QVector3D up = m_listenerUp;
+ dir.normalize();
+ up.normalize();
+ QVector3D u = up - dir * QVector3D::dotProduct(dir, up);
+ u.normalize();
+ d->setListenerOrientation(dir, u);
+}
+
+void QAudioEngine::setListenerGain(qreal gain)
+{
+ d->setListenerGain(gain);
+}
+
+qreal QAudioEngine::dopplerFactor() const
+{
+ return m_dopplerFactor;
+}
+
+void QAudioEngine::setDopplerFactor(qreal dopplerFactor)
+{
+ m_dopplerFactor = dopplerFactor;
+ d->setDopplerFactor(dopplerFactor);
+}
+
+qreal QAudioEngine::speedOfSound() const
+{
+ return m_speedOfSound;
+}
+
+void QAudioEngine::setSpeedOfSound(qreal speedOfSound)
+{
+ m_speedOfSound = speedOfSound;
+ d->setSpeedOfSound(speedOfSound);
+}
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 QAUDIOENGINE_P_H
+#define QAUDIOENGINE_P_H
+
+#include <QtCore/QObject>
+#include <QtCore/QMap>
+#include <QtCore/QUrl>
+#include <QtGui/qvector3d.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSoundSource;
+class QSoundBuffer;
+class QAudioEnginePrivate;
+
+class QAudioEngine : public QObject
+{
+ Q_OBJECT
+public:
+ ~QAudioEngine();
+
+ virtual QSoundSource* createSoundSource();
+ virtual void releaseSoundSource(QSoundSource *soundInstance);
+
+ virtual QSoundBuffer* getStaticSoundBuffer(const QUrl& url);
+ virtual void releaseSoundBuffer(QSoundBuffer *buffer);
+
+ virtual bool isLoading() const;
+
+ virtual QVector3D listenerPosition() const;
+ virtual QVector3D listenerDirection() const;
+ virtual QVector3D listenerVelocity() const;
+ virtual QVector3D listenerUp() const;
+ virtual qreal listenerGain() const;
+ virtual void setListenerPosition(const QVector3D& position);
+ virtual void setListenerDirection(const QVector3D& direction);
+ virtual void setListenerVelocity(const QVector3D& velocity);
+ virtual void setListenerUp(const QVector3D& up);
+ virtual void setListenerGain(qreal gain);
+
+ virtual qreal dopplerFactor() const;
+ virtual void setDopplerFactor(qreal dopplerFactor);
+
+ virtual qreal speedOfSound() const;
+ virtual void setSpeedOfSound(qreal speedOfSound);
+
+ static QAudioEngine* create(QObject *parent);
+
+Q_SIGNALS:
+ void isLoadingChanged();
+
+private:
+ QAudioEngine(QObject *parent);
+ QAudioEnginePrivate *d;
+
+ void updateListenerOrientation();
+
+ qreal m_dopplerFactor;
+ qreal m_speedOfSound;
+ QVector3D m_listenerUp;
+ QVector3D m_listenerDirection;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 "qdeclarative_attenuationmodel_p.h"
+#include "qdebug.h"
+
+#define DEBUG_AUDIOENGINE
+
+QT_USE_NAMESPACE
+
+QDeclarativeAttenuationModel::QDeclarativeAttenuationModel(QObject *parent)
+ : QObject(parent)
+ , m_complete(false)
+{
+}
+
+QDeclarativeAttenuationModel::~QDeclarativeAttenuationModel()
+{
+}
+
+void QDeclarativeAttenuationModel::classBegin()
+{
+ if (!parent() || !parent()->inherits("QDeclarativeAudioEngine")) {
+ qWarning("AttenuationModel must be defined inside AudioEngine!");
+ //TODO: COMPILE_EXCEPTION ?
+ return;
+ }
+}
+
+void QDeclarativeAttenuationModel::componentComplete()
+{
+ if (m_name.isEmpty()) {
+ qWarning("AttenuationModel must have a name!");
+ return;
+ }
+ m_complete = true;
+}
+
+QString QDeclarativeAttenuationModel::name() const
+{
+ return m_name;
+}
+
+void QDeclarativeAttenuationModel::setName(const QString& name)
+{
+ if (m_complete) {
+ qWarning("AttenuationModel: you can not change name after initialization.");
+ return;
+ }
+ m_name = name;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+/*!
+ \qmlclass AttenuationModelLinear QDeclarativeAttenuationModelLinear
+ \since 5.0
+ \brief The AttenuationModelLinear element allows you to define a linear attenuation curve for
+ Sound element.
+ \ingroup qml-multimedia
+ \inherits Item
+
+ This element is part of the \bold{QtAudioEngine 1.0} module.
+
+ AttenuationModelLinear must be defined inside AudioEngine.
+
+ \qml
+ import QtQuick 2.0
+ import QtAudioEngine 1.0
+
+
+ Rectangle {
+ color:"white"
+ width: 300
+ height: 500
+
+ AudioEngine {
+ id:audioengine
+
+ AttenuationModelLinear {
+ name:"linear"
+ start: 20
+ end: 180
+ }
+
+ AudioSample {
+ name:"explosion"
+ source: "explosion-02.wav"
+ }
+
+ Sound {
+ name:"explosion"
+ attenuationModel: "linear"
+ PlayVariation {
+ sample:"explosion"
+ }
+ }
+ }
+ }
+ \endqml
+*/
+
+/*!
+ \qmlproperty string AttenuationModelLinear::name
+
+ This property holds the name of AttenuationModelLinear, must be unique among all attenuation
+ models and only defined once.
+*/
+QDeclarativeAttenuationModelLinear::QDeclarativeAttenuationModelLinear(QObject *parent)
+ : QDeclarativeAttenuationModel(parent)
+ , m_start(0)
+ , m_end(1)
+{
+}
+
+void QDeclarativeAttenuationModelLinear::componentComplete()
+{
+ if (m_start > m_end) {
+ qSwap(m_start, m_end);
+ qWarning() << "AttenuationModelLinear[" << m_name << "]: start must be less or equal than end.";
+ }
+ QDeclarativeAttenuationModel::componentComplete();
+}
+
+/*!
+ \qmlproperty real AttenuationModelLinear::start
+
+ This property holds the start distance. There will be no attenuation if the distance from sound
+ to listener is within this range.
+ The default value is 0.
+*/
+qreal QDeclarativeAttenuationModelLinear::startDistance() const
+{
+ return m_start;
+}
+
+void QDeclarativeAttenuationModelLinear::setStartDistance(qreal startDist)
+{
+ if (m_complete) {
+ qWarning() << "AttenuationModelLinear[" << m_name << "]: you can not change properties after initialization.";
+ return;
+ }
+ if (startDist < 0) {
+ qWarning() << "AttenuationModelLinear[" << m_name << "]: start must be no less than 0.";
+ return;
+ }
+ m_start = startDist;
+}
+
+/*!
+ \qmlproperty real AttenuationModelLinear::end
+
+ This property holds the end distance. There will be no sound hearable if the distance from sound
+ to listener is larger than this.
+ The default value is 1.
+*/
+qreal QDeclarativeAttenuationModelLinear::endDistance() const
+{
+ return m_end;
+}
+
+void QDeclarativeAttenuationModelLinear::setEndDistance(qreal endDist)
+{
+ if (m_complete) {
+ qWarning() << "AttenuationModelLinear[" << m_name << "]: you can not change properties after initialization.";
+ return;
+ }
+ if (endDist < 0) {
+ qWarning() << "AttenuationModelLinear[" << m_name << "]: end must be no greater than 0.";
+ return;
+ }
+ m_end = endDist;
+}
+
+qreal QDeclarativeAttenuationModelLinear::calculateGain(const QVector3D &listenerPosition, const QVector3D &sourcePosition) const
+{
+ qreal md = m_end - m_start;
+ if (md == 0)
+ return 1;
+ qreal d = qBound(qreal(0), (listenerPosition - sourcePosition).length() - m_start, md);
+ return qreal(1) - (d / md);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+/*!
+ \qmlclass AttenuationModelInverse QDeclarativeAttenuationModelInverse
+ \since 5.0
+ \brief The AttenuationModelInverse element allows you to define a non-linear attenuation curve
+ for Sound element.
+ \ingroup qml-multimedia
+ \inherits Item
+
+ This element is part of the \bold{QtAudioEngine 1.0} module.
+
+ AttenuationModelInverse must be defined inside AudioEngine.
+
+ \qml
+ import QtQuick 2.0
+ import QtAudioEngine 1.0
+
+
+ Rectangle {
+ color:"white"
+ width: 300
+ height: 500
+
+ AudioEngine {
+ id:audioengine
+
+ AttenuationModelInverse {
+ name:"linear"
+ start: 20
+ end: 500
+ rolloff: 1.5
+ }
+
+ AudioSample {
+ name:"explosion"
+ source: "explosion-02.wav"
+ }
+
+ Sound {
+ name:"explosion"
+ attenuationModel: "linear"
+ PlayVariation {
+ sample:"explosion"
+ }
+ }
+ }
+ }
+ \endqml
+
+ Attenuation factor is calculated as below:
+
+ distance: distance from sound to listener
+ d = min(max(distance, start), end);
+ attenuation = start / (start + (d - start) * rolloff);
+*/
+
+/*!
+ \qmlproperty string AttenuationModelInverse::name
+
+ This property holds the name of AttenuationModelInverse, must be unique among all attenuation
+ models and only defined once.
+*/
+
+/*!
+ \qmlproperty real AttenuationModelInverse::start
+
+ This property holds the start distance. There will be no attenuation if the distance from sound
+ to listener is within this range.
+ The default value is 1.
+*/
+
+/*!
+ \qmlproperty real AttenuationModelInverse::end
+
+ This property holds the end distance. There will be no further attenuation if the distance from
+ sound to listener is larger than this.
+ The default value is 1000.
+*/
+
+/*!
+ \qmlproperty real AttenuationModelInverse::rolloff
+
+ This property holds the rolloff factor. The bigger the value is, the faster the sound attenuates.
+ The default value is 1.
+*/
+
+QDeclarativeAttenuationModelInverse::QDeclarativeAttenuationModelInverse(QObject *parent)
+ : QDeclarativeAttenuationModel(parent)
+ , m_ref(1)
+ , m_max(1000)
+ , m_rolloff(1)
+{
+}
+
+void QDeclarativeAttenuationModelInverse::componentComplete()
+{
+ if (m_ref > m_max) {
+ qSwap(m_ref, m_max);
+ qWarning() << "AttenuationModelInverse[" << m_name << "]: referenceDistance must be less or equal than maxDistance.";
+ }
+ QDeclarativeAttenuationModel::componentComplete();
+}
+
+qreal QDeclarativeAttenuationModelInverse::referenceDistance() const
+{
+ return m_ref;
+}
+
+void QDeclarativeAttenuationModelInverse::setReferenceDistance(qreal referenceDistance)
+{
+ if (m_complete) {
+ qWarning() << "AttenuationModelInverse[" << m_name << "]: you can not change properties after initialization.";
+ return;
+ }
+ if (referenceDistance <= 0) {
+ qWarning() << "AttenuationModelInverse[" << m_name << "]: referenceDistance must be greater than 0.";
+ return;
+ }
+ m_ref = referenceDistance;
+}
+
+qreal QDeclarativeAttenuationModelInverse::maxDistance() const
+{
+ return m_max;
+}
+
+void QDeclarativeAttenuationModelInverse::setMaxDistance(qreal maxDistance)
+{
+ if (m_complete) {
+ qWarning() << "AttenuationModelInverse[" << m_name << "]: you can not change properties after initialization.";
+ return;
+ }
+ if (maxDistance <= 0) {
+ qWarning() << "AttenuationModelInverse[" << m_name << "]: maxDistance must be greater than 0.";
+ return;
+ }
+ m_max = maxDistance;
+}
+
+qreal QDeclarativeAttenuationModelInverse::rolloffFactor() const
+{
+ return m_rolloff;
+}
+
+void QDeclarativeAttenuationModelInverse::setRolloffFactor(qreal rolloffFactor)
+{
+ if (m_complete) {
+ qWarning() << "AttenuationModelInverse[" << m_name << "]: you can not change properties after initialization.";
+ return;
+ }
+ m_rolloff = rolloffFactor;
+}
+
+qreal QDeclarativeAttenuationModelInverse::calculateGain(const QVector3D &listenerPosition, const QVector3D &sourcePosition) const
+{
+ Q_ASSERT(m_ref > 0);
+ return m_ref / (m_ref + (qBound(m_ref, (listenerPosition - sourcePosition).length(), m_max) - m_ref) * m_rolloff);
+}
+
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 QDECLARATIVEATTENUATIONMODEL_P_H
+#define QDECLARATIVEATTENUATIONMODEL_P_H
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QVector3D>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeAttenuationModel : public QObject, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_PROPERTY(QString name READ name WRITE setName)
+
+public:
+ QDeclarativeAttenuationModel(QObject *parent = 0);
+ ~QDeclarativeAttenuationModel();
+
+ void classBegin();
+ void componentComplete();
+
+ QString name() const;
+ void setName(const QString& name);
+
+ virtual qreal calculateGain(const QVector3D &listenerPosition, const QVector3D &sourcePosition) const = 0;
+
+protected:
+ bool m_complete;
+ QString m_name;
+
+private:
+ Q_DISABLE_COPY(QDeclarativeAttenuationModel);
+};
+
+class QDeclarativeAttenuationModelLinear : public QDeclarativeAttenuationModel
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal start READ startDistance WRITE setStartDistance CONSTANT)
+ Q_PROPERTY(qreal end READ endDistance WRITE setEndDistance CONSTANT)
+
+public:
+ QDeclarativeAttenuationModelLinear(QObject *parent = 0);
+
+ void componentComplete();
+
+ qreal startDistance() const;
+ void setStartDistance(qreal startDist);
+
+ qreal endDistance() const;
+ void setEndDistance(qreal endDist);
+
+ qreal calculateGain(const QVector3D &listenerPosition, const QVector3D &sourcePosition) const;
+
+private:
+ Q_DISABLE_COPY(QDeclarativeAttenuationModelLinear);
+ qreal m_start;
+ qreal m_end;
+};
+
+class QDeclarativeAttenuationModelInverse : public QDeclarativeAttenuationModel
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal start READ referenceDistance WRITE setReferenceDistance CONSTANT)
+ Q_PROPERTY(qreal end READ maxDistance WRITE setMaxDistance CONSTANT)
+ Q_PROPERTY(qreal rolloff READ rolloffFactor WRITE setRolloffFactor CONSTANT)
+
+public:
+ QDeclarativeAttenuationModelInverse(QObject *parent = 0);
+
+ void componentComplete();
+
+ qreal referenceDistance() const;
+ void setReferenceDistance(qreal referenceDistance);
+
+ qreal maxDistance() const;
+ void setMaxDistance(qreal maxDistance);
+
+ qreal rolloffFactor() const;
+ void setRolloffFactor(qreal rolloffFactor);
+
+ qreal calculateGain(const QVector3D &listenerPosition, const QVector3D &sourcePosition) const;
+
+private:
+ Q_DISABLE_COPY(QDeclarativeAttenuationModelInverse);
+ qreal m_ref;
+ qreal m_max;
+ qreal m_rolloff;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 "qdeclarative_audiocategory_p.h"
+#include "qdebug.h"
+
+#define DEBUG_AUDIOENGINE
+
+QT_USE_NAMESPACE
+
+/*!
+ \qmlclass AudioCategory QDeclarativeAudioCategory
+ \since 5.0
+ \brief The AudioCategory element allows you to control all active sound instances by group
+ \ingroup qml-multimedia
+ \inherits Item
+
+ This element is part of the \bold{QtAudioEngine 1.0} module.
+
+ AudioCategory element can be accessed through AudioEngine::categories with its unique name and
+ must be defined inside AudioEngine.
+
+ \qml
+ import QtQuick 2.0
+ import QtAudioEngine 1.0
+
+ Rectangle {
+ color:"white"
+ width: 300
+ height: 500
+
+ AudioEngine {
+ id:audioengine
+
+ AudioCategory {
+ name: "sfx"
+ volume: 0.8
+ }
+
+ AudioSample {
+ name:"explosion"
+ source: "explosion-02.wav"
+ }
+
+ Sound {
+ name:"explosion"
+ category: "sfx"
+ PlayVariation {
+ sample:"explosion"
+ }
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: {
+ audioengine.categories["sfx"].volume = 0.5;
+ }
+ }
+ }
+ \endqml
+
+ Sound elements can be grouped togather by specifying the category property. When you change the
+ volume of a category, all audio output from related elements will be affected as well.
+
+ Note: there will always be an AudioCategory named \c default whether you explicitly define it or
+ not. If you do not specify any category for a Sound element, it will be grouped into the \c default
+ category.
+
+*/
+QDeclarativeAudioCategory::QDeclarativeAudioCategory(QObject *parent)
+ : QObject(parent)
+ , m_complete(false)
+ , m_volume(1)
+{
+}
+
+QDeclarativeAudioCategory::~QDeclarativeAudioCategory()
+{
+}
+
+void QDeclarativeAudioCategory::classBegin()
+{
+ if (!parent() || !parent()->inherits("QDeclarativeAudioEngine")) {
+ qWarning("AudioCategory must be defined inside AudioEngine!");
+ return;
+ }
+}
+
+void QDeclarativeAudioCategory::componentComplete()
+{
+ if (m_name.isEmpty()) {
+ qWarning("AudioCategory must have a name!");
+ return;
+ }
+ m_complete = true;
+}
+
+/*!
+ \qmlproperty real AudioCategory::volume
+
+ This property holds the volume of the category and will modulate all audio output from the
+ element which belongs to this category.
+*/
+qreal QDeclarativeAudioCategory::volume() const
+{
+ return m_volume;
+}
+
+void QDeclarativeAudioCategory::setVolume(qreal volume)
+{
+ if (m_volume == volume)
+ return;
+ m_volume = volume;
+ emit volumeChanged(m_volume);
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QDeclarativeAudioCategory[" << m_name << "] setVolume(" << volume << ")";
+#endif
+}
+
+/*!
+ \qmlproperty string AudioCategory::name
+
+ This property holds the name of AudioCategory. The name must be unique among all categories and only
+ defined once.
+*/
+void QDeclarativeAudioCategory::setName(const QString& name)
+{
+ if (m_complete) {
+ qWarning("AudioCategory: you can not change name after initialization.");
+ return;
+ }
+ m_name = name;
+}
+
+QString QDeclarativeAudioCategory::name() const
+{
+ return m_name;
+}
+
+/*!
+ \qmlmethod AudioCategory::stop()
+
+ Stops all active sound instances which belong to this category.
+*/
+void QDeclarativeAudioCategory::stop()
+{
+ emit stopped();
+}
+
+/*!
+ \qmlmethod AudioCategory::pause()
+
+ Pauses all active sound instances which belong to this category.
+*/
+void QDeclarativeAudioCategory::pause()
+{
+ emit paused();
+}
+
+/*!
+ \qmlmethod AudioCategory::pause()
+
+ Resumes all active sound instances from paused state which belong to this category.
+*/
+void QDeclarativeAudioCategory::resume()
+{
+ emit resumed();
+}
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 QDECLARATIVEAUDIOCATEGORY_P_H
+#define QDECLARATIVEAUDIOCATEGORY_P_H
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeAudioCategory : public QObject, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_PROPERTY(qreal volume READ volume WRITE setVolume NOTIFY volumeChanged)
+ Q_PROPERTY(QString name READ name WRITE setName)
+
+public:
+ QDeclarativeAudioCategory(QObject *parent = 0);
+ ~QDeclarativeAudioCategory();
+
+ void classBegin();
+ void componentComplete();
+
+ qreal volume() const;
+ void setVolume(qreal volume);
+
+ QString name() const;
+ void setName(const QString& name);
+
+Q_SIGNALS:
+ void volumeChanged(qreal newVolume);
+ void stopped();
+ void paused();
+ void resumed();
+
+public Q_SLOTS:
+ void stop();
+ void pause();
+ void resume();
+
+private:
+ Q_DISABLE_COPY(QDeclarativeAudioCategory);
+ bool m_complete;
+ QString m_name;
+ qreal m_volume;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 "qdeclarative_audioengine_p.h"
+#include "qdeclarative_audiolistener_p.h"
+#include "qdeclarative_audiocategory_p.h"
+#include "qdeclarative_audiosample_p.h"
+#include "qdeclarative_sound_p.h"
+#include "qdeclarative_playvariation_p.h"
+#include "qdeclarative_attenuationmodel_p.h"
+#include "qdeclarative_soundinstance_p.h"
+#include "qsoundinstance_p.h"
+#include <QtDeclarative/qdeclarativeengine.h>
+#include "qdebug.h"
+
+#define DEBUG_AUDIOENGINE
+
+QT_USE_NAMESPACE
+
+/*!
+ \qmlclass AudioEngine QDeclarativeAudioEngine
+ \since 5.0
+ \brief The AudioEngine element allows you to organize all your 3d audio content in one place.
+ \ingroup qml-multimedia
+ \inherits Item
+
+ This element is part of the \bold{QtAudioEngine 1.0} module.
+
+ \qml
+ import QtQuick 2.0
+ import QtAudioEngine 1.0
+
+ Rectangle {
+ color:"white"
+ width: 300
+ height: 500
+
+ AudioEngine {
+ id:audioengine
+
+ AudioSample {
+ name:"explosion"
+ source: "explosion-02.wav"
+ }
+
+ Sound {
+ name:"explosion"
+ PlayVariation {
+ sample:"explosion"
+ }
+ }
+
+ dopplerFactor: 1
+ speedOfSound: 343.33
+
+ listener.up:"0,0,1"
+ listener.position:"0,0,0"
+ listener.velocity:"0,0,0"
+ listener.direction:"0,1,0"
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: {
+ audioengine.sounds["explosion"].play();
+ }
+ }
+ }
+ \endqml
+
+ The \c AudioEngine element acts as a central library for configuring all 3d audio content in an
+ app, so you should define only one such element in your app.
+
+ It is mostly used as a container to access other elements such as AudioCategory, AudioSample and
+ Sound.
+
+ \sa AudioCategory, AudioSample, Sound, SoundInstance, AttenuationModelLinear, AttenuationModelInverse
+*/
+
+QDeclarativeAudioEngine::QDeclarativeAudioEngine(QObject *parent)
+ : QObject(parent)
+ , m_complete(false)
+ , m_defaultCategory(0)
+ , m_defaultAttenuationModel(0)
+ , m_audioEngine(0)
+{
+ m_audioEngine = QAudioEngine::create(this);
+ connect(m_audioEngine, SIGNAL(isLoadingChanged()), this, SIGNAL(isLoadingChanged()));
+ connect(m_audioEngine, SIGNAL(isLoadingChanged()), this, SLOT(handleLoadingChanged()));
+ m_listener = new QDeclarativeAudioListener(this);
+ m_updateTimer.setInterval(100);
+ connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateSoundInstances()));
+}
+
+QDeclarativeAudioEngine::~QDeclarativeAudioEngine()
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QDeclarativeAudioEngine::dtor"
+ << "active = " << m_activeSoundInstances.count()
+ << "pool = " << m_soundInstancePool.count();
+#endif
+ qDeleteAll(m_activeSoundInstances);
+ m_activeSoundInstances.clear();
+
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "for pool";
+#endif
+ qDeleteAll(m_soundInstancePool);
+ m_soundInstancePool.clear();
+}
+
+void QDeclarativeAudioEngine::classBegin()
+{
+}
+
+bool QDeclarativeAudioEngine::isReady() const
+{
+ return m_complete;
+}
+
+QAudioEngine* QDeclarativeAudioEngine::engine() const
+{
+ return m_audioEngine;
+}
+
+QDeclarativeSoundInstance* QDeclarativeAudioEngine::newDeclarativeSoundInstance(bool managed)
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QDeclarativeAudioEngine::newDeclarativeSoundInstance(" << managed << ")";
+#endif
+ QDeclarativeSoundInstance *instance = 0;
+ if (managed) {
+ if (m_managedDeclSndInstancePool.count() > 0) {
+ instance = m_managedDeclSndInstancePool.last();
+ m_managedDeclSndInstancePool.pop_back();
+ } else {
+ instance = new QDeclarativeSoundInstance(this);
+ qmlEngine(instance)->setObjectOwnership(instance, QDeclarativeEngine::CppOwnership);
+ instance->setEngine(this);
+ }
+ m_managedDeclSoundInstances.push_back(instance);
+ } else {
+ instance = new QDeclarativeSoundInstance();
+ instance->setEngine(this);
+ qmlEngine(instance)->setObjectOwnership(instance, QDeclarativeEngine::JavaScriptOwnership);
+ }
+ return instance;
+}
+
+void QDeclarativeAudioEngine::releaseManagedDeclarativeSoundInstance(QDeclarativeSoundInstance* declSndInstance)
+{
+ declSndInstance->setSound(QString());
+ m_managedDeclSndInstancePool.push_back(declSndInstance);
+}
+
+/*!
+ \qmlproperty int AudioEngine::liveInstances
+
+ This property indicates how many live sound instances there are at the moment.
+*/
+int QDeclarativeAudioEngine::liveInstanceCount() const
+{
+ return m_activeSoundInstances.count();
+}
+
+QSoundInstance* QDeclarativeAudioEngine::newSoundInstance(const QString &name)
+{
+ QSoundInstance *instance = 0;
+ if (m_soundInstancePool.count() > 0) {
+ instance = m_soundInstancePool.last();
+ m_soundInstancePool.pop_back();
+ } else {
+ instance = new QSoundInstance(this);
+ }
+ instance->bindSoundDescription(qobject_cast<QDeclarativeSound*>(qvariant_cast<QObject*>(m_sounds.value(name))));
+ m_activeSoundInstances.push_back(instance);
+ if (!m_updateTimer.isActive())
+ m_updateTimer.start();
+ emit liveInstanceCountChanged();
+ return instance;
+}
+
+void QDeclarativeAudioEngine::releaseSoundInstance(QSoundInstance* instance)
+{
+ instance->bindSoundDescription(0);
+ m_activeSoundInstances.removeOne(instance);
+ m_soundInstancePool.push_back(instance);
+ emit liveInstanceCountChanged();
+}
+
+void QDeclarativeAudioEngine::componentComplete()
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "AudioEngine begin initialization";
+#endif
+ if (!m_defaultCategory) {
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "creating default category";
+#endif
+ m_defaultCategory = new QDeclarativeAudioCategory(this);
+ m_defaultCategory->classBegin();
+ m_defaultCategory->setName(QString::fromLatin1("default"));
+ m_defaultCategory->setVolume(1);
+ m_defaultCategory->componentComplete();
+ }
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "init samples" << m_samples.keys().count();
+#endif
+ foreach (const QString& key, m_samples.keys()) {
+ QDeclarativeAudioSample *sample = qobject_cast<QDeclarativeAudioSample*>(
+ qvariant_cast<QObject*>(m_samples[key]));
+ if (!sample) {
+ qWarning() << "accessing invalid sample[" << key << "]";
+ continue;
+ }
+ sample->init();
+ }
+
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "init sounds" << m_sounds.keys().count();
+#endif
+ foreach (const QString& key, m_sounds.keys()) {
+ QDeclarativeSound *sound = qobject_cast<QDeclarativeSound*>(
+ qvariant_cast<QObject*>(m_sounds[key]));
+
+ if (!sound) {
+ qWarning() << "accessing invalid sound[" << key << "]";
+ continue;
+ }
+ QDeclarativeAudioCategory *category = m_defaultCategory;
+ if (m_categories.contains(sound->category())) {
+ category = qobject_cast<QDeclarativeAudioCategory*>(
+ qvariant_cast<QObject*>(m_categories[sound->category()]));
+ }
+ sound->setCategoryObject(category);
+
+ QDeclarativeAttenuationModel *attenuationModel = 0;
+ if (sound->attenuationModel().isEmpty()) {
+ if (m_defaultAttenuationModel)
+ attenuationModel = m_defaultAttenuationModel;
+ } else if (m_attenuationModels.contains(sound->attenuationModel())){
+ attenuationModel = m_attenuationModels[sound->attenuationModel()];
+ } else {
+ qWarning() << "Sound[" << sound->name() << "] contains invalid attenuationModel["
+ << sound->attenuationModel() << "]";
+ }
+ sound->setAttenuationModelObject(attenuationModel);
+
+ foreach (QDeclarativePlayVariation* playVariation, sound->playlist()) {
+ if (m_samples.contains(playVariation->sample())) {
+ playVariation->setSampleObject(
+ qobject_cast<QDeclarativeAudioSample*>(
+ qvariant_cast<QObject*>(m_samples[playVariation->sample()])));
+ } else {
+ qWarning() << "Sound[" << sound->name() << "] contains invalid sample["
+ << playVariation->sample() << "] for its playVarations";
+ }
+ }
+ }
+ m_complete = true;
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "AudioEngine ready.";
+#endif
+ emit ready();
+}
+
+void QDeclarativeAudioEngine::updateSoundInstances()
+{
+ for (QList<QDeclarativeSoundInstance*>::Iterator it = m_managedDeclSoundInstances.begin();
+ it != m_managedDeclSoundInstances.end();) {
+ QDeclarativeSoundInstance *declSndInstance = *it;
+ if (declSndInstance->state() == QDeclarativeSoundInstance::StopppedState) {
+ it = m_managedDeclSoundInstances.erase(it);
+ releaseManagedDeclarativeSoundInstance(declSndInstance);
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "AudioEngine removed managed sounce instance";
+#endif
+ } else {
+ declSndInstance->updatePosition(qreal(0.1));
+ ++it;
+ }
+ }
+
+ QVector3D listenerPosition = this->listener()->position();
+ foreach (QSoundInstance *instance, m_activeSoundInstances) {
+ if (instance->state() == QSoundInstance::PlayingState
+ && instance->attenuationEnabled()) {
+ instance->update3DVolume(listenerPosition);
+ }
+ }
+
+ if (m_activeSoundInstances.count() == 0)
+ m_updateTimer.stop();
+}
+
+void QDeclarativeAudioEngine::appendFunction(QDeclarativeListProperty<QObject> *property, QObject *value)
+{
+ QDeclarativeAudioEngine* engine = static_cast<QDeclarativeAudioEngine*>(property->object);
+ if (engine->m_complete) {
+ qWarning("AudioEngine: cannot add child after initialization!");
+ return;
+ }
+
+ QDeclarativeSound *sound = qobject_cast<QDeclarativeSound*>(value);
+ if (sound) {
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "add QDeclarativeSound[" << sound->name() << "]";
+#endif
+ if (engine->m_sounds.contains(sound->name())) {
+ qWarning() << "Failed to add Sound[" << sound->name() << "], already exists!";
+ return;
+ }
+ engine->m_sounds.insert(sound->name(), QVariant::fromValue(value));
+ return;
+ }
+
+ QDeclarativeAudioSample *sample = qobject_cast<QDeclarativeAudioSample*>(value);
+ if (sample) {
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "add QDeclarativeAudioSample[" << sample->name() << "]";
+#endif
+ if (engine->m_samples.contains(sample->name())) {
+ qWarning() << "Failed to add AudioSample[" << sample->name() << "], already exists!";
+ return;
+ }
+ engine->m_samples.insert(sample->name(), QVariant::fromValue(value));
+ return;
+ }
+
+ QDeclarativeAudioCategory *category = qobject_cast<QDeclarativeAudioCategory*>(value);
+ if (category) {
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "add QDeclarativeAudioCategory[" << category->name() << "]";
+#endif
+ if (engine->m_categories.contains(category->name())) {
+ qWarning() << "Failed to add AudioCategory[" << category->name() << "], already exists!";
+ return;
+ }
+ engine->m_categories.insert(category->name(), QVariant::fromValue(value));
+ if (category->name() == QLatin1String("default")) {
+ engine->m_defaultCategory = category;
+ }
+ }
+
+ QDeclarativeAttenuationModel *attenModel = qobject_cast<QDeclarativeAttenuationModel*>(value);
+ if (attenModel) {
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "add AttenuationModel[" << attenModel->name() << "]";
+#endif
+ if (attenModel->name() == QLatin1String("default")) {
+ engine->m_defaultAttenuationModel = attenModel;
+ }
+ if (engine->m_attenuationModels.contains(attenModel->name())) {
+ qWarning() << "Failed to add AttenuationModel[" << attenModel->name() << "], already exists!";
+ return;
+ }
+ engine->m_attenuationModels.insert(attenModel->name(), attenModel);
+ return;
+ }
+
+ qWarning("Unknown child type for AudioEngine!");
+}
+
+QDeclarativeListProperty<QObject> QDeclarativeAudioEngine::bank()
+{
+ return QDeclarativeListProperty<QObject>(this, 0, appendFunction);
+}
+
+/*!
+ \qmlproperty map AudioEngine::categories
+
+ Container of all AudioCategory elements.
+*/
+QObject* QDeclarativeAudioEngine::categories()
+{
+ return &m_categories;
+}
+
+/*!
+ \qmlproperty map AudioEngine::samples
+
+ Container of all AudioSample elements.
+*/
+QObject* QDeclarativeAudioEngine::samples()
+{
+ return &m_samples;
+}
+
+/*!
+ \qmlproperty map AudioEngine::sounds
+
+ Container of all Sound elements.
+*/
+QObject* QDeclarativeAudioEngine::sounds()
+{
+ return &m_sounds;
+}
+
+/*!
+ \qmlproperty AudioListener AudioEngine::listener
+
+ This property holds the listener object. You can change various
+ properties to affect the 3D positioning of sounds.
+
+ \sa AudioListener
+*/
+QDeclarativeAudioListener* QDeclarativeAudioEngine::listener() const
+{
+ return m_listener;
+}
+
+/*!
+ \qmlproperty real AudioEngine::dopplerFactor
+
+ This property holds a simple scaling for the effect of doppler shift.
+*/
+qreal QDeclarativeAudioEngine::dopplerFactor() const
+{
+ return m_audioEngine->dopplerFactor();
+}
+
+void QDeclarativeAudioEngine::setDopplerFactor(qreal dopplerFactor)
+{
+ m_audioEngine->setDopplerFactor(dopplerFactor);
+}
+
+/*!
+ \qmlproperty real AudioEngine::speedOfSound
+
+ This property holds the reference value of the sound speed which will be used in doppler shift
+ calculation.
+*/
+qreal QDeclarativeAudioEngine::speedOfSound() const
+{
+ return m_audioEngine->speedOfSound();
+}
+
+void QDeclarativeAudioEngine::setSpeedOfSound(qreal speedOfSound)
+{
+ m_audioEngine->setSpeedOfSound(speedOfSound);
+}
+
+/*!
+ \qmlproperty real AudioEngine::loading
+
+ This property indicates if the audio engine is loading any audio sample at the moment. This may
+ be useful if you specified the preloaded property in AudioSample and would like to show a loading screen
+ to the user before all audio samples are loaded.
+
+ /sa finishedLoading, AudioSample::preloaded
+*/
+bool QDeclarativeAudioEngine::isLoading() const
+{
+ return m_audioEngine->isLoading();
+}
+
+void QDeclarativeAudioEngine::handleLoadingChanged()
+{
+ if (!isLoading())
+ emit finishedLoading();
+}
+
+/*!
+ \qmlsignal AudioEngine::onLiveInstancesChanged()
+
+ This handler is called when \l liveInstances is changed
+*/
+
+/*!
+ \qmlsignal AudioEngine::onLoadingChanged()
+
+ This handler is called when \l loading is changed
+*/
+
+/*!
+ \qmlsignal AudioEngine::finishedLoading()
+
+ This handler is called when \l loading is finished
+*/
+QT_END_NAMESPACE
+
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 QDECLARATIVEAUDIOENGINE_P_H
+#define QDECLARATIVEAUDIOENGINE_P_H
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtDeclarative/qdeclarativepropertymap.h>
+#include <QtCore/QMap>
+#include <QtCore/QList>
+#include <QTimer>
+#include "qaudioengine_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeSoundInstance;
+class QDeclarativeAudioListener;
+class QDeclarativeAudioCategory;
+class QDeclarativeAudioSample;
+class QDeclarativeSound;
+class QDeclarativePlayVariation;
+class QAudioCategory;
+class QDeclarativeAttenuationModel;
+class QSoundInstance;
+
+class QDeclarativeAudioEngine : public QObject, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_PROPERTY(QDeclarativeListProperty<QObject> bank READ bank CONSTANT)
+ Q_PROPERTY(QObject* categories READ categories CONSTANT)
+ Q_PROPERTY(QObject* samples READ samples CONSTANT)
+ Q_PROPERTY(QObject* sounds READ sounds CONSTANT)
+ Q_PROPERTY(bool loading READ isLoading NOTIFY isLoadingChanged)
+ Q_PROPERTY(int liveInstances READ liveInstanceCount NOTIFY liveInstanceCountChanged)
+ Q_PROPERTY(QDeclarativeAudioListener* listener READ listener CONSTANT)
+ Q_PROPERTY(qreal dopplerFactor READ dopplerFactor WRITE setDopplerFactor)
+ Q_PROPERTY(qreal speedOfSound READ speedOfSound WRITE setSpeedOfSound)
+ Q_CLASSINFO("DefaultProperty", "bank")
+
+public:
+ QDeclarativeAudioEngine(QObject *parent = 0);
+ ~QDeclarativeAudioEngine();
+
+ void classBegin();
+ void componentComplete();
+
+ //This is used for tracking all objects declared inside AudioEngine
+ //see appendFunction
+ QDeclarativeListProperty<QObject> bank();
+
+ QObject* categories();
+ QObject* samples();
+ QObject* sounds();
+
+ QDeclarativeAudioListener* listener() const;
+
+ qreal dopplerFactor() const;
+ void setDopplerFactor(qreal dopplerFactor);
+
+ qreal speedOfSound() const;
+ void setSpeedOfSound(qreal speedOfSound);
+
+ bool isLoading() const;
+
+ int liveInstanceCount() const;
+
+ //for child elements
+ bool isReady() const;
+ QAudioEngine* engine() const;
+
+ //if managed, then the instance should start playing immediately and will be collected
+ //when the playback finished
+ QDeclarativeSoundInstance* newDeclarativeSoundInstance(bool managed);
+
+ //internal sound instance is different from declarativeSoundInstance
+ //declarative instance is more like a soundInstance helper which can
+ //switch to different sound instance conveniently while sound instance
+ //must be mapped to one sound definition.
+ QSoundInstance* newSoundInstance(const QString &name);
+ void releaseSoundInstance(QSoundInstance* instance);
+
+Q_SIGNALS:
+ void ready();
+ void liveInstanceCountChanged();
+ void isLoadingChanged();
+ void finishedLoading();
+
+private Q_SLOTS:
+ void updateSoundInstances();
+ void handleLoadingChanged();
+
+private:
+ Q_DISABLE_COPY(QDeclarativeAudioEngine);
+ bool m_complete;
+
+ //see bank()
+ static void appendFunction(QDeclarativeListProperty<QObject> *property, QObject *value);
+
+ QDeclarativeAudioListener *m_listener;
+ QDeclarativeAudioCategory* m_defaultCategory;
+ QDeclarativePropertyMap m_categories;
+ QDeclarativePropertyMap m_samples;
+ QDeclarativePropertyMap m_sounds;
+
+ //Use strong type here since no need to for AttenuationModel to be accessible directly by user
+ //after config stage
+ QDeclarativeAttenuationModel *m_defaultAttenuationModel;
+ QMap<QString, QDeclarativeAttenuationModel*> m_attenuationModels;
+
+ QAudioEngine *m_audioEngine;
+
+ //for execution stage management
+ QList<QSoundInstance*> m_soundInstancePool;
+ QList<QSoundInstance*> m_activeSoundInstances;
+
+ QTimer m_updateTimer;
+ QList<QDeclarativeSoundInstance*> m_managedDeclSoundInstances;
+ QList<QDeclarativeSoundInstance*> m_managedDeclSndInstancePool;
+ void releaseManagedDeclarativeSoundInstance(QDeclarativeSoundInstance* declSndInstance);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 "qdeclarative_audiolistener_p.h"
+#include "qdeclarative_audioengine_p.h"
+#include "qdebug.h"
+
+#define DEBUG_AUDIOENGINE
+
+QT_USE_NAMESPACE
+
+/*!
+ \qmlclass AudioListener QDeclarativeAudioListener
+ \since 5.0
+ \brief The AudioListener element allows you to control global listener parameters.
+ \ingroup qml-multimedia
+ \inherits Item
+
+ This element is part of the \bold{QtAudioEngine 1.0} module.
+
+ AudioListener will have only one global instance and you can either access it through the
+ listener property of AudioEngine:
+
+ \qml
+ import QtQuick 2.0
+ import QtAudioEngine 1.0
+
+ Rectangle {
+ color:"white"
+ width: 300
+ height: 500
+
+ AudioEngine {
+ id:audioengine
+ listener.up:"0,0,1"
+ listener.velocity:"0,0,0"
+ listener.direction:"0,1,0"
+ listener.position:Qt.vector3d(observer.x, observer.y, 0);
+ }
+
+ Item {
+ id: observer
+ x: 10 + observer.percent * 100
+ y: 20 + observer.percent * 80
+ property real percent: 0
+ SequentialAnimation on percent {
+ loops: Animation.Infinite
+ running: true
+ NumberAnimation {
+ duration: 8000
+ from: 0
+ to: 1
+ }
+
+ }
+ }
+ }
+ \endqml
+
+ or alternatively, by defining an AudioListener element outside AudioEngine:
+
+ \qml
+ import QtQuick 2.0
+ import QtAudioEngine 1.0
+
+ Rectangle {
+ color:"white"
+ width: 300
+ height: 500
+
+ AudioEngine {
+ id:audioengine
+ listener.up:"0,0,1"
+ listener.velocity:"0,0,0"
+ listener.direction:"0,1,0"
+ }
+
+ AudioListener {
+ engine:audioengine
+ position: Qt.vector3d(observer.x, observer.y, 0);
+ }
+
+ Item {
+ id: observer
+ x: 10 + observer.percent * 100
+ y: 20 + observer.percent * 80
+ property real percent: 0
+ SequentialAnimation on percent {
+ loops: Animation.Infinite
+ running: true
+ NumberAnimation {
+ duration: 8000
+ from: 0
+ to: 1
+ }
+
+ }
+ }
+ }
+ \endqml
+
+ This separate AudioListener definition is allowed to make qml bindings easier in some case.
+*/
+
+QDeclarativeAudioListener::QDeclarativeAudioListener(QObject *parent)
+ : QObject(parent)
+ , m_engine(0)
+{
+ m_engine = qobject_cast<QDeclarativeAudioEngine*>(parent);
+}
+
+QDeclarativeAudioListener::~QDeclarativeAudioListener()
+{
+}
+
+/*!
+ \qmlproperty AudioEngine AudioListener::engine
+
+ This property holds the reference to AudioEngine, must be set only once.
+*/
+QDeclarativeAudioEngine* QDeclarativeAudioListener::engine() const
+{
+ return m_engine;
+}
+
+void QDeclarativeAudioListener::setEngine(QDeclarativeAudioEngine *engine)
+{
+ setParent(engine);
+ m_engine = engine;
+}
+
+/*!
+ \qmlproperty vector3d AudioListener::position
+
+ This property holds the 3d position of the listener.
+*/
+QVector3D QDeclarativeAudioListener::position() const
+{
+ return m_engine->engine()->listenerPosition();
+}
+
+void QDeclarativeAudioListener::setPosition(const QVector3D &position)
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QDeclarativeAudioListener::setPosition";
+#endif
+ m_engine->engine()->setListenerPosition(position);
+ emit positionChanged();
+}
+
+/*!
+ \qmlproperty vector3d AudioListener::direction
+
+ This property holds the normalized 3d direction vector of the listener.
+*/
+QVector3D QDeclarativeAudioListener::direction() const
+{
+ return m_engine->engine()->listenerDirection();
+}
+
+void QDeclarativeAudioListener::setDirection(const QVector3D &direction)
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QDeclarativeAudioListener::setDirection";
+#endif
+ m_engine->engine()->setListenerDirection(direction);
+ emit directionChanged();
+}
+
+/*!
+ \qmlproperty vector3d AudioListener::velocity
+
+ This property holds the 3d velocity vector of the listener.
+*/
+QVector3D QDeclarativeAudioListener::velocity() const
+{
+ return m_engine->engine()->listenerVelocity();
+}
+
+void QDeclarativeAudioListener::setVelocity(const QVector3D &velocity)
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QDeclarativeAudioListener::setVelocity";
+#endif
+ m_engine->engine()->setListenerVelocity(velocity);
+ emit velocityChanged();
+}
+
+/*!
+ \qmlproperty vector3d AudioListener::up
+
+ This property holds the normalized 3d up vector of the listener.
+*/
+QVector3D QDeclarativeAudioListener::up() const
+{
+ return m_engine->engine()->listenerUp();
+}
+
+void QDeclarativeAudioListener::setUp(const QVector3D &up)
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QDeclarativeAudioListener::setUp";
+#endif
+ m_engine->engine()->setListenerUp(up);
+ emit upChanged();
+}
+
+/*!
+ \qmlproperty real AudioListener::gain
+
+ This property will modulate all audio output from audio engine elements.
+*/
+qreal QDeclarativeAudioListener::gain() const
+{
+ return m_engine->engine()->listenerGain();
+}
+
+void QDeclarativeAudioListener::setGain(qreal gain)
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QDeclarativeAudioListener::setGain";
+#endif
+ m_engine->engine()->setListenerGain(gain);
+ emit gainChanged();
+}
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 QDECLARATIVEAUDIOLISTENER_P_H
+#define QDECLARATIVEAUDIOLISTENER_P_H
+
+#include <QtCore/QObject>
+#include <QtGui/qvector3d.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeAudioEngine;
+
+class QDeclarativeAudioListener : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QDeclarativeAudioEngine* engine READ engine WRITE setEngine)
+ Q_PROPERTY(QVector3D position READ position WRITE setPosition NOTIFY positionChanged)
+ Q_PROPERTY(QVector3D direction READ direction WRITE setDirection NOTIFY directionChanged)
+ Q_PROPERTY(QVector3D velocity READ velocity WRITE setVelocity NOTIFY velocityChanged)
+ Q_PROPERTY(QVector3D up READ up WRITE setUp NOTIFY upChanged)
+ Q_PROPERTY(qreal gain READ gain WRITE setGain NOTIFY gainChanged)
+
+public:
+ QDeclarativeAudioListener(QObject *parent = 0);
+ ~QDeclarativeAudioListener();
+
+ QDeclarativeAudioEngine* engine() const;
+ void setEngine(QDeclarativeAudioEngine *engine);
+
+ QVector3D position() const;
+ void setPosition(const QVector3D &position);
+
+ QVector3D direction() const;
+ void setDirection(const QVector3D &direction);
+
+ QVector3D up() const;
+ void setUp(const QVector3D &up);
+
+ QVector3D velocity() const;
+ void setVelocity(const QVector3D &velocity);
+
+ qreal gain() const;
+ void setGain(qreal gain);
+
+Q_SIGNALS:
+ void positionChanged();
+ void directionChanged();
+ void velocityChanged();
+ void upChanged();
+ void gainChanged();
+
+private:
+ Q_DISABLE_COPY(QDeclarativeAudioListener);
+ QDeclarativeAudioEngine *m_engine;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 "qdeclarative_audiosample_p.h"
+#include "qdeclarative_audioengine_p.h"
+#include "qdebug.h"
+#include "qsoundbuffer_p.h"
+#include "qaudioengine_p.h"
+
+#define DEBUG_AUDIOENGINE
+
+QT_USE_NAMESPACE
+
+/*!
+ \qmlclass AudioSample QDeclarativeAudioSample
+ \since 5.0
+ \brief The AudioSample element allows you to load audio samples, mostly wav file.
+ \ingroup qml-multimedia
+ \inherits Item
+
+ This element is part of the \bold{QtAudioEngine 1.0} module.
+
+ AudioSample element can be accessed through AudioEngine::samples with its unique name and must
+ be defined inside AudioEngine.
+
+ \qml
+ import QtQuick 2.0
+ import QtAudioEngine 1.0
+
+ Rectangle {
+ color:"white"
+ width: 300
+ height: 500
+
+ AudioEngine {
+ id:audioengine
+
+ AudioSample {
+ name:"explosion"
+ source: "explosion-02.wav"
+ }
+ }
+ }
+ \endqml
+*/
+QDeclarativeAudioSample::QDeclarativeAudioSample(QObject *parent)
+ : QObject(parent)
+ , m_complete(false)
+ , m_streaming(false)
+ , m_preloaded(false)
+ , m_soundBuffer(0)
+{
+}
+
+QDeclarativeAudioSample::~QDeclarativeAudioSample()
+{
+}
+
+void QDeclarativeAudioSample::classBegin()
+{
+ if (!parent() || !parent()->inherits("QDeclarativeAudioEngine")) {
+ qWarning("AudioSample must be defined inside AudioEngine!");
+ return;
+ }
+}
+
+void QDeclarativeAudioSample::componentComplete()
+{
+ if (m_name.isEmpty()) {
+ qWarning("AudioSample must have a name!");
+ return;
+ }
+ m_complete = true;
+}
+
+QUrl QDeclarativeAudioSample::source() const
+{
+ return m_url;
+}
+
+void QDeclarativeAudioSample::setSource(const QUrl& url)
+{
+ if (m_complete) {
+ qWarning("AudioSample: source not changable after initialization.");
+ return;
+ }
+ m_url = url;
+}
+
+bool QDeclarativeAudioSample::isStreaming() const
+{
+ return m_streaming;
+}
+
+/*!
+ \qmlproperty bool AudioSample::preloaded
+
+ This property holds indicates whether this sample needs to be preloaded or not.
+ If true, the audio engine will start loading the sample file immediately when the app started,
+ otherwise the sample will not be loaded untill be used by other element.
+*/
+
+bool QDeclarativeAudioSample::isPreloaded() const
+{
+ return m_preloaded;
+}
+
+/*!
+ \qmlproperty bool AudioSample::isLoaded
+
+ This property holds indicates whether this sample has been loaded into memory or not.
+*/
+bool QDeclarativeAudioSample::isLoaded() const
+{
+ if (!m_soundBuffer)
+ return false;
+ return m_soundBuffer->isReady();
+}
+
+/*!
+ \qmlproperty AudioSample::load()
+
+ Starts loading the sample into memory if not loaded.
+*/
+void QDeclarativeAudioSample::load()
+{
+ if (isLoaded())
+ return;
+ if (!m_soundBuffer) {
+ m_preloaded = true;
+ return;
+ }
+ m_soundBuffer->load();
+}
+
+void QDeclarativeAudioSample::setPreloaded(bool preloaded)
+{
+ if (m_complete) {
+ qWarning("AudioSample: preloaded not changable after initialization.");
+ return;
+ }
+ m_preloaded = preloaded;
+}
+
+void QDeclarativeAudioSample::setStreaming(bool streaming)
+{
+ if (m_complete) {
+ qWarning("AudioSample: streaming not changable after initialization.");
+ return;
+ }
+ m_streaming = streaming;
+}
+
+/*!
+ \qmlproperty string AudioSample::name
+
+ This property holds the name of AudioSample, must be unique among all samples and only
+ defined once.
+*/
+QString QDeclarativeAudioSample::name() const
+{
+ return m_name;
+}
+
+void QDeclarativeAudioSample::setName(const QString& name)
+{
+ if (m_complete) {
+ qWarning("AudioSample: name not changable after initialization.");
+ return;
+ }
+ m_name = name;
+}
+
+void QDeclarativeAudioSample::init()
+{
+ if (m_streaming) {
+ //TODO
+
+ } else {
+ m_soundBuffer =
+ qobject_cast<QDeclarativeAudioEngine*>(parent())->engine()->getStaticSoundBuffer(m_url);
+ if (m_soundBuffer->isReady()) {
+ emit loadedChanged();
+ } else {
+ connect(m_soundBuffer, SIGNAL(ready()), this, SIGNAL(loadedChanged()));
+ }
+ if (m_preloaded) {
+ m_soundBuffer->load();
+ }
+ }
+}
+
+QSoundBuffer* QDeclarativeAudioSample::soundBuffer() const
+{
+ return m_soundBuffer;
+}
+
+/*!
+ \qmlsignal AudioSample::onLoadedChanged()
+
+ This handler is called when \l loaded is changed
+*/
+
+
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 QDECLARATIVEAUDIOSAMPLE_P_H
+#define QDECLARATIVEAUDIOSAMPLE_P_H
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSoundBuffer;
+
+class QDeclarativeAudioSample : public QObject, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(QUrl source READ source WRITE setSource)
+ Q_PROPERTY(bool preloaded READ isPreloaded WRITE setPreloaded)
+ Q_PROPERTY(bool streaming READ isStreaming WRITE setStreaming)
+ Q_PROPERTY(bool loaded READ isLoaded NOTIFY loadedChanged)
+
+public:
+ QDeclarativeAudioSample(QObject *parent = 0);
+ ~QDeclarativeAudioSample();
+
+ void classBegin();
+ void componentComplete();
+
+ QString name() const;
+ void setName(const QString& name);
+
+ QUrl source() const;
+ void setSource(const QUrl& url);
+
+ bool isStreaming() const;
+ void setStreaming(bool streaming);
+
+ bool isPreloaded() const;
+ void setPreloaded(bool preloaded);
+
+ bool isLoaded() const;
+
+ QSoundBuffer* soundBuffer() const;
+
+ //called by QDeclarativeAudioEngine
+ void init();
+
+Q_SIGNALS:
+ void loadedChanged();
+
+public Q_SLOTS:
+ void load();
+
+private:
+ Q_DISABLE_COPY(QDeclarativeAudioSample);
+ bool m_complete;
+ QString m_name;
+ QUrl m_url;
+ bool m_streaming;
+ bool m_preloaded;
+
+ QSoundBuffer *m_soundBuffer;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 "qdeclarative_playvariation_p.h"
+#include "qdeclarative_audioengine_p.h"
+#include "qsoundinstance_p.h"
+#include "qdebug.h"
+
+#define DEBUG_AUDIOENGINE
+
+QT_USE_NAMESPACE
+
+/*!
+ \qmlclass PlayVariation QDeclarativePlayVariation
+ \since 5.0
+ \brief The PlayVariation element allows you to define a playback variation for \l Sound element.
+ So each time the playback of the same sound can be a slightly different even with the same
+ AudioSample.
+
+ \ingroup qml-multimedia
+ \inherits Item
+
+ This element is part of the \bold{QtAudioEngine 1.0} module.
+
+ PlayVariation must be defined inside \l Sound element.
+
+ \qml
+ import QtQuick 2.0
+ import QtAudioEngine 1.0
+
+ Rectangle {
+ color:"white"
+ width: 300
+ height: 500
+
+ AudioEngine {
+ id:audioengine
+
+ AudioSample {
+ name:"explosion01"
+ source: "explosion-01.wav"
+ }
+
+ AudioSample {
+ name:"explosion02"
+ source: "explosion-02.wav"
+ }
+
+ Sound {
+ name:"explosion"
+ PlayVariation {
+ sample:"explosion01"
+ minPitch: 0.8
+ maxPitch: 1.1
+ }
+ PlayVariation {
+ sample:"explosion01"
+ minGain: 1.1
+ maxGain: 1.5
+ }
+ }
+ }
+ }
+ \endqml
+
+*/
+QDeclarativePlayVariation::QDeclarativePlayVariation(QObject *parent)
+ : QObject(parent)
+ , m_complete(false)
+ , m_looping(false)
+ , m_maxGain(1)
+ , m_minGain(1)
+ , m_maxPitch(1)
+ , m_minPitch(1)
+ , m_sampleObject(0)
+{
+}
+
+QDeclarativePlayVariation::~QDeclarativePlayVariation()
+{
+}
+
+void QDeclarativePlayVariation::classBegin()
+{
+ if (!parent() || !parent()->inherits("QDeclarativeSound")) {
+ qWarning("PlayVariation must be defined inside Sound!");
+ return;
+ }
+}
+
+void QDeclarativePlayVariation::componentComplete()
+{
+ if (m_maxGain < m_minGain) {
+ qWarning("PlayVariation: maxGain must be no less than minGain");
+ qSwap(m_minGain, m_maxGain);
+ }
+ if (m_maxPitch < m_minPitch) {
+ qWarning("PlayVariation: maxPitch must be no less than minPitch");
+ qSwap(m_minPitch, m_maxPitch);
+ }
+ m_complete = true;
+}
+
+/*!
+ \qmlproperty string PlayVariation::sample
+
+ This property specifies which \l AudioSample this variation will use.
+*/
+QString QDeclarativePlayVariation::sample() const
+{
+ return m_sample;
+}
+
+void QDeclarativePlayVariation::setSample(const QString& sample)
+{
+ if (m_complete) {
+ qWarning("PlayVariation: cannot change properties after initialization.");
+ return;
+ }
+ m_sample = sample;
+}
+
+/*!
+ \qmlproperty bool PlayVariation::looping
+
+ This property indicates whether the playback will be looped or not.
+*/
+bool QDeclarativePlayVariation::isLooping() const
+{
+ return m_looping;
+}
+
+void QDeclarativePlayVariation::setLooping(bool looping)
+{
+ if (m_complete) {
+ qWarning("PlayVariation: cannot change properties after initialization.");
+ return;
+ }
+ m_looping = looping;
+}
+
+/*!
+ \qmlproperty real PlayVariation::maxGain
+
+ This property specifies the maximum gain adjustment that can be applied in any playback.
+*/
+qreal QDeclarativePlayVariation::maxGain() const
+{
+ return m_maxGain;
+}
+
+void QDeclarativePlayVariation::setMaxGain(qreal maxGain)
+{
+ if (m_complete) {
+ qWarning("PlayVariation: cannot change properties after initialization.");
+ return;
+ }
+ if (maxGain <= 0) {
+ qWarning("PlayVariation: maxGain must be greater than 0");
+ return;
+ }
+ m_maxGain = maxGain;
+}
+
+/*!
+ \qmlproperty real PlayVariation::minGain
+
+ This property specifies the minimum gain adjustment that can be applied in any playback.
+*/
+qreal QDeclarativePlayVariation::minGain() const
+{
+ return m_minGain;
+}
+
+void QDeclarativePlayVariation::setMinGain(qreal minGain)
+{
+ if (m_complete) {
+ qWarning("PlayVariation: cannot change properties after initialization.");
+ return;
+ }
+ if (minGain < 0) {
+ qWarning("PlayVariation: minGain must be no less than 0");
+ return;
+ }
+ m_minGain = minGain;
+}
+
+/*!
+ \qmlproperty real PlayVariation::maxPitch
+
+ This property specifies the maximum pitch adjustment that can be applied in any playback.
+*/
+qreal QDeclarativePlayVariation::maxPitch() const
+{
+ return m_maxPitch;
+}
+
+void QDeclarativePlayVariation::setMaxPitch(qreal maxPitch)
+{
+ if (m_complete) {
+ qWarning("PlayVariation: cannot change properties after initialization.");
+ return;
+ }
+ if (maxPitch < 0) {
+ qWarning("PlayVariation: maxPitch must be no less than 0");
+ return;
+ }
+ m_maxPitch = maxPitch;
+}
+
+/*!
+ \qmlproperty real PlayVariation::minPitch
+
+ This property specifies the minimum pitch adjustment that can be applied in any playback.
+*/
+qreal QDeclarativePlayVariation::minPitch() const
+{
+ return m_minPitch;
+}
+
+void QDeclarativePlayVariation::setMinPitch(qreal minPitch)
+{
+ if (m_complete) {
+ qWarning("PlayVariation: cannot change properties after initialization.");
+ return;
+ }
+ if (m_minPitch < 0) {
+ qWarning("PlayVariation: m_minPitch must be no less than 0");
+ return;
+ }
+ m_minPitch = minPitch;
+}
+
+QDeclarativeAudioSample* QDeclarativePlayVariation::sampleObject() const
+{
+ return m_sampleObject;
+}
+
+void QDeclarativePlayVariation::setSampleObject(QDeclarativeAudioSample *sampleObject)
+{
+ m_sampleObject = sampleObject;
+}
+
+void QDeclarativePlayVariation::applyParameters(QSoundInstance *soundInstance)
+{
+ qreal pitch = qreal(qrand() % 1001) * 0.001f * (m_maxPitch - m_minPitch) + m_minPitch;
+ qreal gain = qreal(qrand() % 1001) * 0.001f * (m_maxGain - m_minGain) + m_minGain;
+ soundInstance->updateVariationParameters(pitch, gain, m_looping);
+}
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 QDECLARATIVEPLAYVARIATION_P_H
+#define QDECLARATIVEPLAYVARIATION_P_H
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeAudioSample;
+class QSoundInstance;
+
+class QDeclarativePlayVariation : public QObject, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_PROPERTY(QString sample READ sample WRITE setSample)
+ Q_PROPERTY(bool looping READ isLooping WRITE setLooping)
+ Q_PROPERTY(qreal maxGain READ maxGain WRITE setMaxGain)
+ Q_PROPERTY(qreal minGain READ minGain WRITE setMinGain)
+ Q_PROPERTY(qreal maxPitch READ maxPitch WRITE setMaxPitch)
+ Q_PROPERTY(qreal minPitch READ minPitch WRITE setMinPitch)
+
+public:
+ QDeclarativePlayVariation(QObject *parent = 0);
+ ~QDeclarativePlayVariation();
+
+ void classBegin();
+ void componentComplete();
+
+ QString sample() const;
+ void setSample(const QString& sample);
+
+ bool isLooping() const;
+ void setLooping(bool looping);
+
+ qreal maxGain() const;
+ void setMaxGain(qreal maxGain);
+ qreal minGain() const;
+ void setMinGain(qreal minGain);
+
+ qreal maxPitch() const;
+ void setMaxPitch(qreal maxPitch);
+ qreal minPitch() const;
+ void setMinPitch(qreal minPitch);
+
+ //called by QDeclarativeAudioEngine
+ void setSampleObject(QDeclarativeAudioSample *sampleObject);
+ QDeclarativeAudioSample* sampleObject() const;
+
+ void applyParameters(QSoundInstance *soundInstance);
+
+private:
+ Q_DISABLE_COPY(QDeclarativePlayVariation);
+ bool m_complete;
+ QString m_sample;
+ bool m_looping;
+ qreal m_maxGain;
+ qreal m_minGain;
+ qreal m_maxPitch;
+ qreal m_minPitch;
+ QDeclarativeAudioSample *m_sampleObject;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 "qdeclarative_sound_p.h"
+#include "qdeclarative_audiocategory_p.h"
+#include "qdeclarative_attenuationmodel_p.h"
+#include "qdeclarative_soundinstance_p.h"
+#include "qdeclarative_audioengine_p.h"
+#include "qdebug.h"
+
+#define DEBUG_AUDIOENGINE
+
+QT_USE_NAMESPACE
+
+QDeclarativeSoundCone::QDeclarativeSoundCone(QObject *parent)
+ : QObject(parent)
+ , m_innerAngle(360)
+ , m_outerAngle(360)
+ , m_outerGain(0)
+{
+}
+
+/*!
+ \qmlproperty real Sound::cone.innerAngle
+
+ This property holds the innerAngle for Sound definition.
+ The range is [0, 360] degree. There is no directional attenuation within innerAngle.
+*/
+qreal QDeclarativeSoundCone::innerAngle() const
+{
+ return m_innerAngle;
+}
+
+void QDeclarativeSoundCone::setInnerAngle(qreal innerAngle)
+{
+ QDeclarativeSound *s = qobject_cast<QDeclarativeSound*>(parent());
+ if (s && s->m_complete)
+ return;
+ if (innerAngle < 0 || innerAngle > 360) {
+ qWarning() << "innerAngle should be within[0, 360] degrees";
+ return;
+ }
+ m_innerAngle = innerAngle;
+}
+
+/*!
+ \qmlproperty real Sound::cone.outerAngle
+
+ This property holds the outerAngle for Sound definition.
+ The range is [0, 360] degree. All audio output from this sound will be attenuated by \l outerGain
+ outside outerAngle.
+*/
+qreal QDeclarativeSoundCone::outerAngle() const
+{
+ return m_outerAngle;
+}
+
+void QDeclarativeSoundCone::setOuterAngle(qreal outerAngle)
+{
+ QDeclarativeSound *s = qobject_cast<QDeclarativeSound*>(parent());
+ if (s && s->m_complete)
+ return;
+ if (outerAngle < 0 || outerAngle > 360) {
+ qWarning() << "outerAngle should be within[0, 360] degrees";
+ return;
+ }
+ m_outerAngle = outerAngle;
+}
+
+/*!
+ \qmlproperty real Sound::cone.outerGain
+
+ This property holds attenuation value for directional attenuation of this sound.
+ The range is [0, 1]. All audio output from this sound will be attenuated by outerGain
+ outside \l outerAngle.
+*/
+qreal QDeclarativeSoundCone::outerGain() const
+{
+ return m_outerGain;
+}
+
+void QDeclarativeSoundCone::setOuterGain(qreal outerGain)
+{
+ QDeclarativeSound *s = qobject_cast<QDeclarativeSound*>(parent());
+ if (s && s->m_complete)
+ return;
+ if (outerGain < 0 || outerGain > 1) {
+ qWarning() << "outerGain should no less than 0 and no more than 1";
+ return;
+ }
+ m_outerGain = outerGain;
+}
+
+void QDeclarativeSoundCone::componentComplete()
+{
+ if (m_outerAngle < m_innerAngle) {
+ m_outerAngle = m_innerAngle;
+ }
+}
+
+////////////////////////////////////////////////////////////
+/*!
+ \qmlclass Sound QDeclarativeSound
+ \since 5.0
+ \brief The Sound element allows you to define a variety of samples and parameters to be used for
+ SoundInstance.
+ \ingroup qml-multimedia
+ \inherits Item
+
+ This element is part of the \bold{QtAudioEngine 1.0} module.
+
+ Sound element can be accessed through AudioEngine::sounds with its unique name and must be
+ defined inside AudioEngine.
+
+ \qml
+ import QtQuick 2.0
+ import QtAudioEngine 1.0
+
+ Rectangle {
+ color:"white"
+ width: 300
+ height: 500
+
+ AudioEngine {
+ id:audioengine
+
+ AudioSample {
+ name:"explosion01"
+ source: "explosion-01.wav"
+ }
+
+ AudioSample {
+ name:"explosion02"
+ source: "explosion-02.wav"
+ }
+
+ Sound {
+ name:"explosion"
+ PlayVariation {
+ sample:"explosion01"
+ minPitch: 0.8
+ maxPitch: 1.1
+ }
+ PlayVariation {
+ sample:"explosion01"
+ minGain: 1.1
+ maxGain: 1.5
+ }
+ }
+ }
+ MouseArea {
+ anchors.fill: parent
+ onPressed: {
+ audioengine.sounds["explosion"].play();
+ }
+ }
+ }
+ \endqml
+*/
+
+QDeclarativeSound::QDeclarativeSound(QObject *parent)
+ : QObject(parent)
+ , m_complete(false)
+ , m_playType(Random)
+ , m_attenuationModelObject(0)
+ , m_categoryObject(0)
+{
+ m_cone = new QDeclarativeSoundCone(this);
+}
+
+QDeclarativeSound::~QDeclarativeSound()
+{
+}
+
+void QDeclarativeSound::classBegin()
+{
+ if (!parent() || !parent()->inherits("QDeclarativeAudioEngine")) {
+ qWarning("Sound must be defined inside AudioEngine!");
+ return;
+ }
+}
+
+void QDeclarativeSound::componentComplete()
+{
+ m_complete = true;
+ m_cone->componentComplete();
+}
+
+/*!
+ \qmlproperty enueration Sound::playType
+
+ This property holds the playType. It can be one of:
+
+ \list
+ \o Random - randomly picks up a play variation when playback is triggered
+ \o Sequential - plays each variation in sequence when playback is triggered
+ \endlist
+
+ The default value is Random.
+*/
+QDeclarativeSound::PlayType QDeclarativeSound::playType() const
+{
+ return m_playType;
+}
+
+void QDeclarativeSound::setPlayType(PlayType playType)
+{
+ if (m_complete) {
+ qWarning("Sound: playType not changable after initialization.");
+ return;
+ }
+ m_playType = playType;
+}
+
+/*!
+ \qmlproperty string Sound::category
+
+ This property specifies which AudioCategory this sound belongs to.
+*/
+QString QDeclarativeSound::category() const
+{
+ return m_category;
+}
+
+void QDeclarativeSound::setCategory(const QString& category)
+{
+ if (m_complete) {
+ qWarning("Sound: category not changable after initialization.");
+ return;
+ }
+ m_category = category;
+}
+
+/*!
+ \qmlproperty string Sound::name
+
+ This property holds the name of Sound, must be unique among all sounds and only
+ defined once.
+*/
+QString QDeclarativeSound::name() const
+{
+ return m_name;
+}
+
+void QDeclarativeSound::setName(const QString& name)
+{
+ if (m_complete) {
+ qWarning("Sound: category not changable after initialization.");
+ return;
+ }
+ m_name = name;
+}
+
+/*!
+ \qmlproperty string Sound::attenuationModel
+
+ This property specifies which attenuation model this sound will apply.
+*/
+QString QDeclarativeSound::attenuationModel() const
+{
+ return m_attenuationModel;
+}
+
+int QDeclarativeSound::genVariationIndex(int oldVariationIndex)
+{
+ if (m_playlist.count() == 0)
+ return -1;
+
+ if (m_playlist.count() == 1)
+ return 0;
+
+ switch (m_playType) {
+ case QDeclarativeSound::Random: {
+ if (oldVariationIndex < 0)
+ oldVariationIndex = 0;
+ return (oldVariationIndex + (qrand() % (m_playlist.count() + 1))) % m_playlist.count();
+ }
+ default:
+ return (oldVariationIndex + 1) % m_playlist.count();
+ }
+}
+
+QDeclarativePlayVariation* QDeclarativeSound::getVariation(int index)
+{
+ Q_ASSERT(index >= 0 && index < m_playlist.count());
+ return m_playlist[index];
+}
+
+void QDeclarativeSound::setAttenuationModel(QString attenuationModel)
+{
+ if (m_complete) {
+ qWarning("Sound: attenuationModel not changable after initialization.");
+ return;
+ }
+ m_attenuationModel = attenuationModel;
+}
+
+QDeclarativeSoundCone* QDeclarativeSound::cone() const
+{
+ return m_cone;
+}
+
+QDeclarativeAttenuationModel* QDeclarativeSound::attenuationModelObject() const
+{
+ return m_attenuationModelObject;
+}
+
+void QDeclarativeSound::setAttenuationModelObject(QDeclarativeAttenuationModel *attenuationModelObject)
+{
+ m_attenuationModelObject = attenuationModelObject;
+}
+
+QDeclarativeAudioCategory* QDeclarativeSound::categoryObject() const
+{
+ return m_categoryObject;
+}
+
+void QDeclarativeSound::setCategoryObject(QDeclarativeAudioCategory *categoryObject)
+{
+ m_categoryObject = categoryObject;
+}
+
+QDeclarativeListProperty<QDeclarativePlayVariation> QDeclarativeSound::playVariationlist()
+{
+ return QDeclarativeListProperty<QDeclarativePlayVariation>(this, 0, appendFunction);
+}
+
+QList<QDeclarativePlayVariation*>& QDeclarativeSound::playlist()
+{
+ return m_playlist;
+}
+
+void QDeclarativeSound::appendFunction(QDeclarativeListProperty<QDeclarativePlayVariation> *property, QDeclarativePlayVariation *value)
+{
+ QDeclarativeSound *sound = static_cast<QDeclarativeSound*>(property->object);
+ if (sound->m_complete) {
+ qWarning("Sound: PlayVariation not addable after initialization.");
+ return;
+ }
+ sound->m_playlist.append(value);
+}
+
+/*!
+ \qmlmethod Sound::play()
+
+ Creates a new \l SoundInstance and starts playing.
+ Position, direction and velocity are all set to \c "0,0,0".
+*/
+void QDeclarativeSound::play()
+{
+ play(QVector3D(), QVector3D(), QVector3D(), 1, 1);
+}
+
+/*!
+ \qmlmethod Sound::play(gain)
+
+ Creates a new SoundInstance and starts playing with the adjusted \a gain.
+ Position, direction and velocity are all set to \c "0,0,0".
+*/
+void QDeclarativeSound::play(qreal gain)
+{
+ play(QVector3D(), QVector3D(), QVector3D(), gain, 1);
+}
+
+/*!
+ \qmlmethod Sound::play(gain, pitch)
+
+ Creates a new SoundInstance and starts playing with the adjusted \a gain and \a pitch.
+ Position, direction and velocity are all set to \c "0,0,0".
+*/
+void QDeclarativeSound::play(qreal gain, qreal pitch)
+{
+ play(QVector3D(), QVector3D(), QVector3D(), gain, pitch);
+}
+
+/*!
+ \qmlmethod Sound::play(position)
+
+ Creates a new SoundInstance and starts playing with specified \a position.
+ Direction and velocity are all set to \c "0,0,0".
+*/
+void QDeclarativeSound::play(const QVector3D& position)
+{
+ play(position, QVector3D(), QVector3D(), 1, 1);
+}
+
+/*!
+ \qmlmethod Sound::play(position, velocity)
+
+ Creates a new SoundInstance and starts playing with specified \a position and \a velocity.
+ Direction is set to \c "0,0,0".
+*/
+void QDeclarativeSound::play(const QVector3D& position, const QVector3D& velocity)
+{
+ play(position, velocity, QVector3D(), 1, 1);
+}
+
+/*!
+ \qmlmethod Sound::play(position, velocity, direction)
+
+ Creates a new SoundInstance and starts playing with specified \a position, \a velocity and
+ \a direction.
+*/
+void QDeclarativeSound::play(const QVector3D& position, const QVector3D& velocity,
+ const QVector3D& direction)
+{
+ play(position, velocity, direction, 1, 1);
+}
+
+/*!
+ \qmlmethod Sound::play(position, gain)
+
+ Creates a new SoundInstance and starts playing with specified \a position and adjusted \a gain.
+ Direction and velocity are all set to \c "0,0,0".
+*/
+void QDeclarativeSound::play(const QVector3D& position, qreal gain)
+{
+ play(position, QVector3D(), QVector3D(), gain, 1);
+}
+
+/*!
+ \qmlmethod Sound::play(position, velocity, gain)
+
+ Creates a new SoundInstance and starts playing with specified \a position, \a velocity and
+ adjusted \a gain.
+ Direction is set to \c "0,0,0".
+*/
+void QDeclarativeSound::play(const QVector3D& position, const QVector3D& velocity, qreal gain)
+{
+ play(position, velocity, QVector3D(), gain, 1);
+}
+
+/*!
+ \qmlmethod Sound::play(position, velocity, direction, gain)
+
+ Creates a new SoundInstance and starts playing with specified \a position, \a velocity,
+ \a direction and adjusted \a gain.
+*/
+void QDeclarativeSound::play(const QVector3D& position, const QVector3D& velocity, const QVector3D& direction, qreal gain)
+{
+ play(position, velocity, direction, gain, 1);
+}
+
+/*!
+ \qmlmethod Sound::play(position, gain, pitch)
+
+ Creates a new SoundInstance and starts playing with specified \a position, adjusted \a gain and
+ \a pitch.
+ Direction and velocity are all set to \c "0,0,0".
+*/
+void QDeclarativeSound::play(const QVector3D& position, qreal gain, qreal pitch)
+{
+ play(position, QVector3D(), QVector3D(), gain, pitch);
+}
+
+/*!
+ \qmlmethod Sound::play(position, velocity, gain, pitch)
+
+ Creates a new SoundInstance and starts playing with specified \a position, \a velocity,
+ adjusted \a gain and \a pitch.
+ Direction is set to \c "0,0,0".
+*/
+void QDeclarativeSound::play(const QVector3D& position, const QVector3D& velocity, qreal gain, qreal pitch)
+{
+ play(position, velocity, QVector3D(), gain, pitch);
+}
+
+/*!
+ \qmlmethod Sound::play(position, velocity, direction, gain, pitch)
+
+ Creates a new SoundInstance and starts playing with specified \a position, \a velocity,
+ \a direction, adjusted \a gain and \a pitch.
+*/
+void QDeclarativeSound::play(const QVector3D& position, const QVector3D& velocity, const QVector3D& direction, qreal gain, qreal pitch)
+{
+ if (!m_complete) {
+ qWarning() << "AudioEngine::play not ready!";
+ return;
+ }
+ QDeclarativeSoundInstance *instance = this->newInstance(true);
+ if (!instance)
+ return;
+ instance->setPosition(position);
+ instance->setVelocity(velocity);
+ instance->setDirection(direction);
+ instance->setGain(gain);
+ instance->setPitch(pitch);
+ instance->setConeInnerAngle(cone()->innerAngle());
+ instance->setConeOuterAngle(cone()->outerAngle());
+ instance->setConeOuterGain(cone()->outerGain());
+ instance->play();
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "Sound[" << m_name << "] play ("
+ << position << ","
+ << velocity <<","
+ << direction << ","
+ << gain << ","
+ << pitch << ")triggered";
+#endif
+
+}
+
+/*!
+ \qmlmethod SoundInstance Sound::newInstance()
+
+ Returns a new \l SoundInstance.
+*/
+QDeclarativeSoundInstance* QDeclarativeSound::newInstance()
+{
+ return newInstance(false);
+}
+
+QDeclarativeSoundInstance* QDeclarativeSound::newInstance(bool managed)
+{
+ QDeclarativeSoundInstance *instance =
+ qobject_cast<QDeclarativeAudioEngine*>(this->parent())->newDeclarativeSoundInstance(managed);
+ instance->setSound(m_name);
+ return instance;
+}
+
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 QDECLARATIVESOUND_P_H
+#define QDECLARATIVESOUND_P_H
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtCore/qlist.h>
+#include "qdeclarative_playvariation_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeAudioCategory;
+class QDeclarativeAttenuationModel;
+class QDeclarativeSoundInstance;
+
+class QDeclarativeSoundCone : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal innerAngle READ innerAngle WRITE setInnerAngle)
+ Q_PROPERTY(qreal outerAngle READ outerAngle WRITE setOuterAngle)
+ Q_PROPERTY(qreal outerGain READ outerGain WRITE setOuterGain)
+public:
+ QDeclarativeSoundCone(QObject *parent = 0);
+
+ //by degree
+ qreal innerAngle() const;
+ void setInnerAngle(qreal innerAngle);
+
+ //by degree
+ qreal outerAngle() const;
+ void setOuterAngle(qreal outerAngle);
+
+ qreal outerGain() const;
+ void setOuterGain(qreal outerGain);
+
+ void componentComplete();
+
+private:
+ Q_DISABLE_COPY(QDeclarativeSoundCone)
+ qreal m_innerAngle;
+ qreal m_outerAngle;
+ qreal m_outerGain;
+};
+
+class QDeclarativeSound : public QObject, public QDeclarativeParserStatus
+{
+ friend class QDeclarativeSoundCone;
+
+ Q_OBJECT
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(PlayType playType READ playType WRITE setPlayType)
+ Q_PROPERTY(QString category READ category WRITE setCategory)
+ Q_PROPERTY(QDeclarativeSoundCone* cone READ cone CONSTANT)
+ Q_PROPERTY(QString attenuationModel READ attenuationModel WRITE setAttenuationModel)
+ Q_PROPERTY(QDeclarativeListProperty<QDeclarativePlayVariation> playVariationlist READ playVariationlist CONSTANT)
+ Q_CLASSINFO("DefaultProperty", "playVariationlist")
+
+ Q_ENUMS(PlayType)
+public:
+ enum PlayType
+ {
+ Random,
+ Sequential
+ };
+
+ QDeclarativeSound(QObject *parent = 0);
+ ~QDeclarativeSound();
+
+ void classBegin();
+ void componentComplete();
+
+ PlayType playType() const;
+ void setPlayType(PlayType playType);
+
+ QString category() const;
+ void setCategory(const QString& category);
+
+ QString name() const;
+ void setName(const QString& name);
+
+ QString attenuationModel() const;
+ void setAttenuationModel(QString attenuationModel);
+
+ QDeclarativeSoundCone* cone() const;
+
+ QDeclarativeAttenuationModel* attenuationModelObject() const;
+ void setAttenuationModelObject(QDeclarativeAttenuationModel *attenuationModelObject);
+ QDeclarativeAudioCategory* categoryObject() const;
+ void setCategoryObject(QDeclarativeAudioCategory *categoryObject);
+
+ int genVariationIndex(int oldVariationIndex);
+ QDeclarativePlayVariation* getVariation(int index);
+
+ //This is used for tracking new PlayVariation declared inside Sound
+ QDeclarativeListProperty<QDeclarativePlayVariation> playVariationlist();
+ QList<QDeclarativePlayVariation*>& playlist();
+
+public Q_SLOTS:
+ void play();
+ void play(qreal gain);
+ void play(qreal gain, qreal pitch);
+ void play(const QVector3D& position);
+ void play(const QVector3D& position, const QVector3D& velocity);
+ void play(const QVector3D& position, const QVector3D& velocity, const QVector3D& direction);
+ void play(const QVector3D& position, qreal gain);
+ void play(const QVector3D& position, const QVector3D& velocity, qreal gain);
+ void play(const QVector3D& position, const QVector3D& velocity, const QVector3D& direction, qreal gain);
+ void play(const QVector3D& position, qreal gain, qreal pitch);
+ void play(const QVector3D& position, const QVector3D& velocity, qreal gain, qreal pitch);
+ void play(const QVector3D& position, const QVector3D& velocity, const QVector3D& direction, qreal gain, qreal pitch);
+ QDeclarativeSoundInstance* newInstance();
+
+private:
+ Q_DISABLE_COPY(QDeclarativeSound)
+ QDeclarativeSoundInstance* newInstance(bool managed);
+ static void appendFunction(QDeclarativeListProperty<QDeclarativePlayVariation> *property, QDeclarativePlayVariation *value);
+ bool m_complete;
+ PlayType m_playType;
+ QString m_name;
+ QString m_category;
+ QString m_attenuationModel;
+ QList<QDeclarativePlayVariation*> m_playlist;
+ QDeclarativeSoundCone *m_cone;
+
+ QDeclarativeAttenuationModel *m_attenuationModelObject;
+ QDeclarativeAudioCategory *m_categoryObject;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 "qdeclarative_soundinstance_p.h"
+#include "qdeclarative_sound_p.h"
+#include "qdeclarative_audioengine_p.h"
+#include "qaudioengine_p.h"
+#include "qsoundinstance_p.h"
+#include "qdebug.h"
+
+#define DEBUG_AUDIOENGINE
+
+QT_USE_NAMESPACE
+
+/*!
+ \qmlclass SoundInstance QDeclarativeSoundInstance
+ \since 5.0
+ \brief The SoundInstance element allows you to play 3d audio content.
+ \ingroup qml-multimedia
+ \inherits Item
+
+ This element is part of the \bold{QtAudioEngine 1.0} module.
+
+ There are two ways to create SoundInstance objects. You can obtain it by calling newInstance
+ method of Sound element:
+
+ \qml
+ import QtQuick 2.0
+ import QtAudioEngine 1.0
+
+ Rectangle {
+ id:root
+ color:"white"
+ width: 300
+ height: 500
+
+ AudioEngine {
+ id:audioengine
+
+ AudioSample {
+ name:"explosion01"
+ source: "explosion-01.wav"
+ }
+
+ Sound {
+ name:"explosion"
+ PlayVariation {
+ sample:"explosion01"
+ }
+ }
+ }
+
+ property variant soundEffect: audioengine.sounds["explosion"].newInstance();
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: {
+ root.soundEffect.play();
+ }
+ }
+ }
+ \endqml
+
+ Or alternatively, you can explicitly define SoundInstance element outside of AudioEngine for
+ easier qml bindings:
+
+ \qml
+ import QtQuick 2.0
+ import QtAudioEngine 1.0
+
+ Rectangle {
+ id:root
+ color:"white"
+ width: 300
+ height: 500
+
+ AudioEngine {
+ id:audioengine
+
+ AudioSample {
+ name:"explosion01"
+ source: "explosion-01.wav"
+ }
+
+ Sound {
+ name:"explosion"
+ PlayVariation {
+ sample:"explosion01"
+ }
+ }
+ }
+
+ Item {
+ id: animator
+ x: 10 + observer.percent * 100
+ y: 20 + observer.percent * 80
+ property real percent: 0
+ SequentialAnimation on percent {
+ loops: Animation.Infinite
+ running: true
+ NumberAnimation {
+ duration: 8000
+ from: 0
+ to: 1
+ }
+
+ }
+ }
+
+ SoundInstance {
+ id:soundEffect
+ engine:audioengine
+ sound:"explosion"
+ position:Qt.vector3d(animator.x, animator.y, 0);
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: {
+ soundEffect.play();
+ }
+ }
+ }
+ \endqml
+*/
+
+QDeclarativeSoundInstance::QDeclarativeSoundInstance(QObject *parent)
+ : QObject(parent)
+ , m_position(0, 0, 0)
+ , m_direction(0, 1, 0)
+ , m_velocity(0, 0, 0)
+ , m_gain(1)
+ , m_pitch(1)
+ , m_requestState(QDeclarativeSoundInstance::StopppedState)
+ , m_coneInnerAngle(360)
+ , m_coneOuterAngle(360)
+ , m_coneOuterGain(0)
+ , m_instance(0)
+ , m_engine(0)
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QDeclarativeSoundInstance::ctor()";
+#endif
+}
+
+/*!
+ \qmlproperty AudioEngine SoundInstance::engine
+
+ This property holds the reference to AudioEngine, must be set only once.
+*/
+QDeclarativeAudioEngine* QDeclarativeSoundInstance::engine() const
+{
+ return m_engine;
+}
+
+void QDeclarativeSoundInstance::setEngine(QDeclarativeAudioEngine *engine)
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QDeclarativeSoundInstance::setEngine(" << engine << ")";
+#endif
+ if (!engine)
+ return;
+
+ if (m_engine) {
+ qWarning("SoundInstance: you can not set different value for engine property");
+ return;
+ }
+ m_engine = engine;
+ if (!m_engine->isReady()) {
+ connect(m_engine, SIGNAL(ready()), this, SLOT(engineComplete()));
+ } else {
+ engineComplete();
+ }
+}
+
+void QDeclarativeSoundInstance::engineComplete()
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QDeclarativeSoundInstance::engineComplete()";
+#endif
+ disconnect(m_engine, SIGNAL(ready()), this, SLOT(engineComplete()));
+ if (m_sound.isEmpty())
+ return;
+
+ //rebind to actual engine resource
+ QString sound = m_sound;
+ m_sound.clear();
+ setSound(sound);
+}
+
+QDeclarativeSoundInstance::~QDeclarativeSoundInstance()
+{
+}
+
+/*!
+ \qmlproperty string SoundInstance::sound
+
+ This property specifies which Sound this SoundInstance will use. Unlike some properties in
+ other elements, this property can be changed dynamically.
+*/
+QString QDeclarativeSoundInstance::sound() const
+{
+ return m_sound;
+}
+
+void QDeclarativeSoundInstance::setSound(const QString& sound)
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QDeclarativeSoundInstance::setSound(" << sound << ")";
+#endif
+ if (m_sound == sound)
+ return;
+
+ if (!m_engine || !m_engine->isReady()) {
+ m_sound = sound;
+ emit soundChanged();
+ return;
+ }
+
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "SoundInstance Element switch sound from [" << m_sound << "] to [" << sound << "]";
+#endif
+
+ stop();
+ dropInstance();
+
+ m_sound = sound;
+ if (!m_sound.isEmpty()) {
+ m_instance = m_engine->newSoundInstance(m_sound);
+ connect(m_instance, SIGNAL(stateChanged(QSoundInstance::State)), this, SLOT(handleStateChanged()));
+ m_instance->setPosition(m_position);
+ m_instance->setDirection(m_direction);
+ m_instance->setVelocity(m_velocity);
+ m_instance->setGain(m_gain);
+ m_instance->setPitch(m_pitch);
+ m_instance->setCone(m_coneInnerAngle, m_coneOuterAngle, m_coneOuterGain);
+ if (m_requestState == QDeclarativeSoundInstance::PlayingState) {
+ m_instance->play();
+ } else if (m_requestState == QDeclarativeSoundInstance::PausedState) {
+ m_instance->pause();
+ }
+ }
+ emit soundChanged();
+}
+
+void QDeclarativeSoundInstance::dropInstance()
+{
+ if (m_instance) {
+ disconnect(m_instance, SIGNAL(stateChanged(QSoundInstance::State)), this, SLOT(handleStateChanged()));
+ m_engine->releaseSoundInstance(m_instance);
+ m_instance = 0;
+ }
+}
+
+/*!
+ \qmlproperty enumeration SoundInstance::state
+
+ This property holds the current playback state. It can be one of:
+
+ \list
+ \o StopppedState
+ \o PlayingState
+ \o PausedState
+ \endlist
+*/
+QDeclarativeSoundInstance::State QDeclarativeSoundInstance::state() const
+{
+ if (m_instance)
+ return State(m_instance->state());
+ return m_requestState;
+}
+
+/*!
+ \qmlmethod SoundInstance::play()
+
+ Starts playback.
+*/
+void QDeclarativeSoundInstance::play()
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QDeclarativeSoundInstance::play()";
+#endif
+ if (!m_instance) {
+ m_requestState = QDeclarativeSoundInstance::PlayingState;
+ return;
+ }
+ m_instance->play();
+}
+
+/*!
+ \qmlmethod SoundInstance::play()
+
+ Stops current playback.
+*/
+void QDeclarativeSoundInstance::stop()
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QDeclarativeSoundInstance::stop()";
+#endif
+ m_requestState = QDeclarativeSoundInstance::StopppedState;
+ if (!m_instance)
+ return;
+ m_instance->stop();
+}
+
+/*!
+ \qmlmethod SoundInstance::play()
+
+ Pauses current playback.
+*/
+void QDeclarativeSoundInstance::pause()
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QDeclarativeSoundInstance::pause()";
+#endif
+ if (!m_instance) {
+ m_requestState = QDeclarativeSoundInstance::PausedState;
+ return;
+ }
+ m_instance->pause();
+}
+
+void QDeclarativeSoundInstance::updatePosition(qreal deltaTime)
+{
+ if (!m_instance || deltaTime == 0 || m_velocity.lengthSquared() == 0)
+ return;
+ setPosition(m_position + m_velocity * deltaTime);
+}
+
+/*!
+ \qmlproperty vector3d SoundInstance::position
+
+ This property holds the current 3d position.
+*/
+QVector3D QDeclarativeSoundInstance::position() const
+{
+ return m_position;
+}
+
+void QDeclarativeSoundInstance::setPosition(const QVector3D& position)
+{
+ if (m_position == position)
+ return;
+ m_position = position;
+ emit positionChanged();
+ if (!m_instance) {
+ return;
+ }
+ m_instance->setPosition(m_position);
+}
+
+/*!
+ \qmlproperty vector3d SoundInstance::direction
+
+ This property holds the current 3d direction.
+*/
+QVector3D QDeclarativeSoundInstance::direction() const
+{
+ return m_direction;
+}
+
+void QDeclarativeSoundInstance::setDirection(const QVector3D& direction)
+{
+ if (m_direction == direction)
+ return;
+ m_direction = direction;
+ emit directionChanged();
+ if (!m_instance) {
+ return;
+ }
+ m_instance->setDirection(m_direction);
+}
+
+/*!
+ \qmlproperty vector3d SoundInstance::velocity
+
+ This property holds the current 3d velocity.
+*/
+QVector3D QDeclarativeSoundInstance::velocity() const
+{
+ return m_velocity;
+}
+
+void QDeclarativeSoundInstance::setVelocity(const QVector3D& velocity)
+{
+ if (m_velocity == velocity)
+ return;
+ m_velocity = velocity;
+ emit velocityChanged();
+ if (!m_instance)
+ return;
+ m_instance->setVelocity(m_velocity);
+}
+
+/*!
+ \qmlproperty vector3d SoundInstance::gain
+
+ This property holds the gain adjustment which will be used to modulate the audio ouput level
+ from this SoundInstance.
+*/
+qreal QDeclarativeSoundInstance::gain() const
+{
+ return m_gain;
+}
+
+void QDeclarativeSoundInstance::setGain(qreal gain)
+{
+ if (gain == m_gain)
+ return;
+ if (gain < 0) {
+ qWarning("gain must be a positive value!");
+ return;
+ }
+ m_gain = gain;
+ emit gainChanged();
+ if (!m_instance)
+ return;
+ m_instance->setGain(m_gain);
+}
+
+/*!
+ \qmlproperty vector3d SoundInstance::gain
+
+ This property holds the pitch adjustment which will be used to modulate the audio pitch
+ from this SoundInstance.
+*/
+qreal QDeclarativeSoundInstance::pitch() const
+{
+ return m_pitch;
+}
+
+void QDeclarativeSoundInstance::setPitch(qreal pitch)
+{
+ if (pitch == m_pitch)
+ return;
+ if (pitch < 0) {
+ qWarning("pitch must be a positive value!");
+ return;
+ }
+ m_pitch = pitch;
+ emit pitchChanged();
+ if (!m_instance)
+ return;
+ m_instance->setPitch(m_pitch);
+}
+
+void QDeclarativeSoundInstance::setConeInnerAngle(qreal innerAngle)
+{
+ if (m_coneInnerAngle == innerAngle)
+ return;
+ m_coneInnerAngle = innerAngle;
+ if (!m_instance)
+ return;
+ m_instance->setCone(m_coneInnerAngle, m_coneOuterAngle, m_coneOuterGain);
+}
+
+void QDeclarativeSoundInstance::setConeOuterAngle(qreal outerAngle)
+{
+ if (m_coneOuterAngle == outerAngle)
+ return;
+ m_coneOuterAngle = outerAngle;
+ if (!m_instance)
+ return;
+ m_instance->setCone(m_coneInnerAngle, m_coneOuterAngle, m_coneOuterGain);
+}
+
+void QDeclarativeSoundInstance::setConeOuterGain(qreal outerGain)
+{
+ if (m_coneOuterGain == outerGain)
+ return;
+ m_coneOuterGain = outerGain;
+ if (!m_instance)
+ return;
+ m_instance->setCone(m_coneInnerAngle, m_coneOuterAngle, m_coneOuterGain);
+}
+
+void QDeclarativeSoundInstance::handleStateChanged()
+{
+ emit stateChanged();
+}
+
+/*!
+ \qmlsignal SoundInstance::onStateChanged(state)
+
+ This handler is called when \l state is changed
+*/
+
+/*!
+ \qmlsignal SoundInstance::onPositionChanged()
+
+ This handler is called when \l position is changed
+*/
+
+/*!
+ \qmlsignal SoundInstance::onDirectionChanged()
+
+ This handler is called when \l direction is changed
+*/
+
+/*!
+ \qmlsignal SoundInstance::onVelocityChanged()
+
+ This handler is called when \l velocity is changed
+*/
+
+/*!
+ \qmlsignal SoundInstance::onGainChanged()
+
+ This handler is called when \l gain is changed
+*/
+
+/*!
+ \qmlsignal SoundInstance::onPitchChanged()
+
+ This handler is called when \l pitch is changed
+*/
+
+/*!
+ \qmlsignal SoundInstance::onSoundChanged()
+
+ This handler is called when \l sound is changed
+*/
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 QDECLARATIVE_SOUNDINSTANCE_P_H
+#define QDECLARATIVE_SOUNDINSTANCE_P_H
+
+#include <QtCore/QObject>
+#include <QtGui/qvector3d.h>
+#include "qsoundinstance_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeSound;
+class QAudioEngine;
+class QDeclarativeAudioEngine;
+
+class QDeclarativeSoundInstance : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QDeclarativeAudioEngine* engine READ engine WRITE setEngine)
+ Q_PROPERTY(QString sound READ sound WRITE setSound NOTIFY soundChanged)
+ Q_PROPERTY(State state READ state NOTIFY stateChanged)
+ Q_PROPERTY(QVector3D position READ position WRITE setPosition NOTIFY positionChanged)
+ Q_PROPERTY(QVector3D direction READ direction WRITE setDirection NOTIFY directionChanged)
+ Q_PROPERTY(QVector3D velocity READ velocity WRITE setVelocity NOTIFY velocityChanged)
+ Q_PROPERTY(qreal gain READ gain WRITE setGain NOTIFY gainChanged)
+ Q_PROPERTY(qreal pitch READ pitch WRITE setPitch NOTIFY pitchChanged)
+
+ Q_ENUMS(State)
+
+public:
+ enum State
+ {
+ StopppedState = QSoundInstance::StopppedState,
+ PlayingState = QSoundInstance::PlayingState,
+ PausedState = QSoundInstance::PausedState
+ };
+
+ QDeclarativeSoundInstance(QObject *parent = 0);
+ ~QDeclarativeSoundInstance();
+
+ QDeclarativeAudioEngine* engine() const;
+ void setEngine(QDeclarativeAudioEngine *engine);
+
+ QString sound() const;
+ void setSound(const QString& sound);
+
+ State state() const;
+
+ QVector3D position() const;
+ void setPosition(const QVector3D& position);
+
+ QVector3D direction() const;
+ void setDirection(const QVector3D& direction);
+
+ QVector3D velocity() const;
+ void setVelocity(const QVector3D& velocity);
+
+ qreal gain() const;
+ void setGain(qreal gain);
+
+ qreal pitch() const;
+ void setPitch(qreal pitch);
+
+ void setConeInnerAngle(qreal innerAngle);
+ void setConeOuterAngle(qreal outerAngle);
+ void setConeOuterGain(qreal outerGain);
+
+Q_SIGNALS:
+ void stateChanged();
+ void positionChanged();
+ void directionChanged();
+ void velocityChanged();
+ void gainChanged();
+ void pitchChanged();
+ void soundChanged();
+
+public Q_SLOTS:
+ void play();
+ void stop();
+ void pause();
+ void updatePosition(qreal deltaTime);
+
+private Q_SLOTS:
+ void handleStateChanged();
+
+private:
+ Q_DISABLE_COPY(QDeclarativeSoundInstance);
+ QString m_sound;
+ QVector3D m_position;
+ QVector3D m_direction;
+ QVector3D m_velocity;
+ qreal m_gain;
+ qreal m_pitch;
+ State m_requestState;
+
+ qreal m_coneInnerAngle;
+ qreal m_coneOuterAngle;
+ qreal m_coneOuterGain;
+
+ void dropInstance();
+
+ QSoundInstance *m_instance;
+ QDeclarativeAudioEngine *m_engine;
+
+
+private Q_SLOTS:
+ void engineComplete();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
--- /dev/null
+plugin declarative_audioengine
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 QSOUNDBUFFER_P_H
+#define QSOUNDBUFFER_P_H
+
+#include <QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSoundBuffer : public QObject
+{
+ Q_OBJECT
+public:
+ virtual bool isReady() const = 0;
+ virtual void load() = 0;
+
+Q_SIGNALS:
+ void ready();
+ void error();
+
+protected:
+ QSoundBuffer(QObject *parent);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSOUNDBUFFER_P_H
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 "qsoundinstance_p.h"
+#include "qsoundsource_p.h"
+#include "qsoundbuffer_p.h"
+#include "qdeclarative_sound_p.h"
+#include "qdeclarative_audiocategory_p.h"
+#include "qdeclarative_audiosample_p.h"
+#include "qdeclarative_attenuationmodel_p.h"
+#include "qdeclarative_playvariation_p.h"
+#include "qdeclarative_audioengine_p.h"
+#include "qdeclarative_audiolistener_p.h"
+
+#include "qdebug.h"
+
+#define DEBUG_AUDIOENGINE
+
+QT_USE_NAMESPACE
+
+QSoundInstance::QSoundInstance(QObject *parent)
+ : QObject(parent)
+ , m_soundSource(0)
+ , m_bindBuffer(0)
+ , m_sound(0)
+ , m_variationIndex(-1)
+ , m_isReady(false)
+ , m_gain(1)
+ , m_attenuationGain(1)
+ , m_varGain(1)
+ , m_pitch(1)
+ , m_varPitch(1)
+ , m_state(QSoundInstance::StopppedState)
+ , m_coneOuterGain(0)
+ , m_engine(0)
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "creating new QSoundInstance";
+#endif
+ m_engine = qobject_cast<QDeclarativeAudioEngine*>(parent);
+}
+
+void QSoundInstance::bindSoundDescription(QDeclarativeSound *sound)
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QSoundInstance::bindSoundDescription" << sound;
+#endif
+ if (m_sound == sound)
+ return;
+
+ if (m_sound && m_sound->categoryObject()) {
+ disconnect(m_sound->categoryObject(), SIGNAL(volumeChanged(qreal)), this, SLOT(categoryVolumeChanged()));
+ disconnect(m_sound->categoryObject(), SIGNAL(paused()), this, SLOT(pause()));
+ disconnect(m_sound->categoryObject(), SIGNAL(stopped()), this, SLOT(stop()));
+ disconnect(m_sound->categoryObject(), SIGNAL(resumed()), this, SLOT(resume()));
+ }
+ m_attenuationGain = 1;
+ m_gain = 1;
+
+ m_sound = sound;
+
+ if (sound) {
+ if (!m_soundSource) {
+ m_soundSource = m_engine->engine()->createSoundSource();
+ connect(m_soundSource, SIGNAL(stateChanged(QSoundSource::State)),
+ this, SLOT(handleSourceStateChanged(QSoundSource::State)));
+ }
+ } else {
+ if (m_soundSource) {
+ detach();
+ m_engine->engine()->releaseSoundSource(m_soundSource);
+ m_soundSource = 0;
+ }
+ }
+
+ if (m_sound) {
+ if (m_sound->categoryObject()) {
+ connect(m_sound->categoryObject(), SIGNAL(volumeChanged(qreal)), this, SLOT(categoryVolumeChanged()));
+ connect(m_sound->categoryObject(), SIGNAL(paused()), this, SLOT(pause()));
+ connect(m_sound->categoryObject(), SIGNAL(stopped()), this, SLOT(stop()));
+ connect(m_sound->categoryObject(), SIGNAL(resumed()), this, SLOT(resume()));
+ }
+ prepareNewVariation();
+ } else {
+ m_variationIndex = -1;
+ }
+}
+
+QSoundInstance::~QSoundInstance()
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QSoundInstance::dtor()";
+#endif
+ if (m_soundSource) {
+ detach();
+ m_engine->engine()->releaseSoundSource(m_soundSource);
+ }
+}
+
+void QSoundInstance::prepareNewVariation()
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QSoundInstance::prepareNewVariation()";
+#endif
+ int newVariationIndex = m_sound->genVariationIndex(m_variationIndex);
+ if (newVariationIndex == m_variationIndex)
+ return;
+ QDeclarativePlayVariation *playVar = m_sound->getVariation(newVariationIndex);
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QSoundInstance: generate new play variation [old:" << m_variationIndex << ", new:" << newVariationIndex << "-" << playVar->sample() << "]";
+#endif
+ m_variationIndex = newVariationIndex;
+ playVar->applyParameters(this);
+ detach();
+
+ m_bindBuffer = playVar->sampleObject()->soundBuffer();
+ if (m_bindBuffer->isReady()) {
+ Q_ASSERT(m_soundSource);
+ m_soundSource->bindBuffer(m_bindBuffer);
+ m_isReady = true;
+ } else {
+ m_bindBuffer->load();
+ connect(m_bindBuffer, SIGNAL(ready()), this, SLOT(bufferReady()));
+ }
+}
+
+void QSoundInstance::bufferReady()
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QSoundInstance::bufferReady()";
+#endif
+ if (!m_soundSource)
+ return;
+ m_soundSource->bindBuffer(m_bindBuffer);
+ disconnect(m_bindBuffer, SIGNAL(ready()), this, SLOT(bufferReady()));
+ m_isReady = true;
+
+ if (m_state == QSoundInstance::PlayingState) {
+ sourcePlay();
+ } else if (m_state == QSoundInstance::PausedState) {
+ sourcePause();
+ }
+}
+
+void QSoundInstance::categoryVolumeChanged()
+{
+ updateGain();
+}
+
+void QSoundInstance::handleSourceStateChanged(QSoundSource::State newState)
+{
+ State ns = State(newState);
+ if (ns == m_state)
+ return;
+ if (ns == QSoundInstance::StopppedState) {
+ prepareNewVariation();
+ }
+ setState(ns);
+}
+
+void QSoundInstance::setState(State state)
+{
+ if (state == m_state)
+ return;
+ m_state = state;
+ emit stateChanged(m_state);
+}
+
+qreal QSoundInstance::categoryVolume() const
+{
+ if (!m_sound)
+ return 1;
+ if (!m_sound->categoryObject())
+ return 1;
+ return m_sound->categoryObject()->volume();
+}
+
+void QSoundInstance::sourceStop()
+{
+ Q_ASSERT(m_soundSource);
+ m_soundSource->stop();
+ setState(QSoundInstance::StopppedState);
+}
+
+void QSoundInstance::detach()
+{
+ sourceStop();
+ m_isReady = false;
+ if (m_soundSource)
+ m_soundSource->unbindBuffer();
+ if (m_bindBuffer) {
+ disconnect(m_bindBuffer, SIGNAL(ready()), this, SLOT(bufferReady()));
+ m_engine->engine()->releaseSoundBuffer(m_bindBuffer);
+ m_bindBuffer = 0;
+ }
+}
+
+void QSoundInstance::play()
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QSoundInstancePrivate::play()";
+#endif
+ if (!m_soundSource || m_state == QSoundInstance::PlayingState)
+ return;
+ if (!m_isReady) {
+ setState(QSoundInstance::PlayingState);
+ return;
+ }
+ sourcePlay();
+ setState(QSoundInstance::PlayingState);
+}
+
+void QSoundInstance::sourcePlay()
+{
+ update3DVolume(m_engine->listener()->position());
+ Q_ASSERT(m_soundSource);
+ m_soundSource->play();
+}
+
+void QSoundInstance::resume()
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QSoundInstancePrivate::resume()";
+#endif
+ if (m_state != QSoundInstance::PausedState)
+ return;
+ play();
+}
+
+void QSoundInstance::pause()
+{
+ if (!m_soundSource || m_state == QSoundInstance::PausedState)
+ return;
+ if (!m_isReady) {
+ setState(QSoundInstance::PausedState);
+ return;
+ }
+ sourcePause();
+ setState(QSoundInstance::PausedState);
+}
+
+void QSoundInstance::sourcePause()
+{
+ Q_ASSERT(m_soundSource);
+ m_soundSource->pause();
+}
+
+void QSoundInstance::stop()
+{
+ if (!m_isReady || !m_soundSource || m_state == QSoundInstance::StopppedState) {
+ setState(QSoundInstance::StopppedState);
+ return;
+ }
+ sourceStop();
+ prepareNewVariation();
+}
+
+QSoundInstance::State QSoundInstance::state() const
+{
+ return m_state;
+}
+
+void QSoundInstance::setPosition(const QVector3D& position)
+{
+ if (!m_soundSource)
+ return;
+ m_soundSource->setPosition(position);
+}
+
+void QSoundInstance::setDirection(const QVector3D& direction)
+{
+ if (!m_soundSource)
+ return;
+ m_soundSource->setDirection(direction);
+}
+
+void QSoundInstance::setVelocity(const QVector3D& velocity)
+{
+ if (!m_soundSource)
+ return;
+ m_soundSource->setVelocity(velocity);
+}
+
+void QSoundInstance::setGain(qreal gain)
+{
+ if (!m_soundSource)
+ return;
+ m_gain = gain;
+ updateGain();
+}
+
+void QSoundInstance::setPitch(qreal pitch)
+{
+ if (!m_soundSource)
+ return;
+ m_pitch = pitch;
+ updatePitch();
+}
+
+void QSoundInstance::setCone(qreal innerAngle, qreal outerAngle, qreal outerGain)
+{
+ if (!m_soundSource)
+ return;
+ m_soundSource->setCone(innerAngle, outerAngle, outerGain);
+}
+
+bool QSoundInstance::attenuationEnabled() const
+{
+ if (!m_sound || !m_sound->attenuationModelObject())
+ return false;
+ return true;
+}
+
+void QSoundInstance::update3DVolume(const QVector3D& listenerPosition)
+{
+ if (!m_sound || !m_soundSource)
+ return;
+ QDeclarativeAttenuationModel *attenModel = m_sound->attenuationModelObject();
+ if (!attenModel)
+ return;
+ m_attenuationGain = attenModel->calculateGain(listenerPosition, m_soundSource->position());
+ updateGain();
+}
+
+void QSoundInstance::updateVariationParameters(qreal varPitch, qreal varGain, bool looping)
+{
+ if (!m_soundSource)
+ return;
+ m_soundSource->setLooping(looping);
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QSoundInstance::updateVariationParameters" << varPitch << varGain << looping;
+#endif
+ m_varPitch = varPitch;
+ m_varGain = varGain;
+ updatePitch();
+ updateGain();
+}
+
+void QSoundInstance::updatePitch()
+{
+ m_soundSource->setPitch(m_pitch * m_varPitch);
+}
+
+void QSoundInstance::updateGain()
+{
+ m_soundSource->setGain(m_gain * m_varGain * m_attenuationGain * categoryVolume());
+}
+
+QT_END_NAMESPACE
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 QSOUNDINSTANCE_P_H
+#define QSOUNDINSTANCE_P_H
+
+#include <QVector3D>
+#include <QObject>
+#include "qsoundsource_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeSound;
+class QDeclarativeAudioEngine;
+
+class QSoundInstance : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QSoundInstance(QObject *parent);
+ ~QSoundInstance();
+
+ void play();
+
+ enum State
+ {
+ StopppedState = QSoundSource::StoppedState,
+ PlayingState = QSoundSource::PlayingState,
+ PausedState = QSoundSource::PausedState
+ };
+ State state() const;
+
+ void setPosition(const QVector3D& position);
+ void setDirection(const QVector3D& direction);
+ void setVelocity(const QVector3D& velocity);
+
+ //this gain and pitch is used for dynamic user control during execution
+ void setGain(qreal gain);
+ void setPitch(qreal pitch);
+ void setCone(qreal innerAngle, qreal outerAngle, qreal outerGain);
+
+ //this varPitch and varGain is calculated from config in PlayVariation
+ void updateVariationParameters(qreal varPitch, qreal varGain, bool looping);
+
+ void bindSoundDescription(QDeclarativeSound *sound);
+
+ void update3DVolume(const QVector3D& listenerPosition);
+
+ bool attenuationEnabled() const;
+
+Q_SIGNALS:
+ void stateChanged(QSoundInstance::State state);
+
+public Q_SLOTS:
+ void pause();
+ void stop();
+
+private Q_SLOTS:
+ void resume();
+ void bufferReady();
+ void categoryVolumeChanged();
+ void handleSourceStateChanged(QSoundSource::State);
+
+private:
+ void setState(State state);
+ void prepareNewVariation();
+ void detach();
+ qreal categoryVolume() const;
+ void updatePitch();
+ void updateGain();
+ void updateConeOuterGain();
+
+ void sourcePlay();
+ void sourcePause();
+ void sourceStop();
+
+ QSoundSource *m_soundSource;
+ QSoundBuffer *m_bindBuffer;
+
+ QDeclarativeSound *m_sound;
+ int m_variationIndex;
+
+ bool m_isReady; //true if the sound source is already bound to some sound buffer
+ qreal m_gain;
+ qreal m_attenuationGain;
+ qreal m_varGain;
+ qreal m_pitch;
+ qreal m_varPitch;
+ State m_state;
+ qreal m_coneOuterGain;
+
+ QDeclarativeAudioEngine *m_engine;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSOUNDINSTANCE_P_H
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 "qaudioengine_openal_p.h"
+#include "qdebug.h"
+
+#define DEBUG_AUDIOENGINE
+
+QT_USE_NAMESPACE
+
+QSoundSourcePrivate::QSoundSourcePrivate(QObject *parent)
+ : QSoundSource(parent)
+ , m_alSource(0)
+ , m_bindBuffer(0)
+ , m_isReady(false)
+ , m_state(QSoundSource::StoppedState)
+ , m_gain(0)
+ , m_pitch(0)
+ , m_coneInnerAngle(0)
+ , m_coneOuterAngle(0)
+ , m_coneOuterGain(1)
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "creating new QSoundSourcePrivate";
+#endif
+ alGenSources(1, &m_alSource);
+ QAudioEnginePrivate::checkNoError("create source");
+ setGain(1);
+ setPitch(1);
+ setCone(360, 360, 0);
+}
+
+QSoundSourcePrivate::~QSoundSourcePrivate()
+{
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QSoundSourcePrivate::dtor";
+#endif
+ release();
+}
+
+void QSoundSourcePrivate::release()
+{
+ if (m_alSource) {
+#ifdef DEBUG_AUDIOENGINE
+ qDebug() << "QSoundSourcePrivate::release";
+#endif
+ stop();
+ unbindBuffer();
+ alDeleteSources(1, &m_alSource);
+ QAudioEnginePrivate::checkNoError("delete source");
+ m_alSource = 0;
+ }
+}
+
+void QSoundSourcePrivate::bindBuffer(QSoundBuffer* soundBuffer)
+{
+ unbindBuffer();
+ Q_ASSERT(soundBuffer->isReady());
+ m_bindBuffer = qobject_cast<QSoundBufferPrivateAL*>(soundBuffer);
+ m_bindBuffer->bindToSource(m_alSource);
+ m_isReady = true;
+}
+
+void QSoundSourcePrivate::unbindBuffer()
+{
+ if (m_bindBuffer) {
+ m_bindBuffer->unbindFromSource(m_alSource);
+ m_bindBuffer = 0;
+ }
+ m_isReady = false;
+ if (m_state != QSoundSource::StoppedState) {
+ m_state = QSoundSource::StoppedState;
+ emit stateChanged(m_state);
+ }
+}
+
+void QSoundSourcePrivate::play()
+{
+ if (!m_alSource || !m_isReady)
+ return;
+ alSourcePlay(m_alSource);
+#ifdef DEBUG_AUDIOENGINE
+ QAudioEnginePrivate::checkNoError("play");
+#endif
+ emit activate(this);
+}
+
+bool QSoundSourcePrivate::isLooping() const
+{
+ if (!m_alSource)
+ return false;
+ ALint looping = 0;
+ alGetSourcei(m_alSource, AL_LOOPING, &looping);
+ return looping == AL_TRUE ? true : false;
+}
+
+void QSoundSourcePrivate::pause()
+{
+ if (!m_alSource || !m_isReady)
+ return;
+ alSourcePause(m_alSource);
+#ifdef DEBUG_AUDIOENGINE
+ QAudioEnginePrivate::checkNoError("pause");
+#endif
+}
+
+void QSoundSourcePrivate::stop()
+{
+ if (!m_alSource)
+ return;
+ alSourceStop(m_alSource);
+#ifdef DEBUG_AUDIOENGINE
+ QAudioEnginePrivate::checkNoError("stop");
+#endif
+}
+
+QSoundSource::State QSoundSourcePrivate::state() const
+{
+ return m_state;
+}
+
+void QSoundSourcePrivate::checkState()
+{
+ QSoundSource::State st;
+ st = QSoundSource::StoppedState;
+ if (m_alSource && m_isReady) {
+ ALint s;
+ alGetSourcei(m_alSource, AL_SOURCE_STATE, &s);
+ switch (s) {
+ case AL_PLAYING:
+ st = QSoundSource::PlayingState;
+ break;
+ case AL_PAUSED:
+ st = QSoundSource::PausedState;
+ break;
+ }
+ }
+ if (st == m_state)
+ return;
+ m_state = st;
+ emit stateChanged(m_state);
+}
+
+void QSoundSourcePrivate::setLooping(bool looping)
+{
+ if (!m_alSource)
+ return;
+ alSourcei(m_alSource, AL_LOOPING, looping ? AL_TRUE : AL_FALSE);
+}
+
+void QSoundSourcePrivate::setPosition(const QVector3D& position)
+{
+ if (!m_alSource)
+ return;
+ alSource3f(m_alSource, AL_POSITION, position.x(), position.y(), position.z());
+#ifdef DEBUG_AUDIOENGINE
+ QAudioEnginePrivate::checkNoError("source set position");
+#endif
+}
+
+void QSoundSourcePrivate::setDirection(const QVector3D& direction)
+{
+ if (!m_alSource)
+ return;
+ alSource3f(m_alSource, AL_DIRECTION, direction.x(), direction.y(), direction.z());
+#ifdef DEBUG_AUDIOENGINE
+ QAudioEnginePrivate::checkNoError("source set direction");
+#endif
+}
+
+void QSoundSourcePrivate::setVelocity(const QVector3D& velocity)
+{
+ if (!m_alSource)
+ return;
+ alSource3f(m_alSource, AL_VELOCITY, velocity.x(), velocity.y(), velocity.z());
+#ifdef DEBUG_AUDIOENGINE
+ QAudioEnginePrivate::checkNoError("source set velocity");
+#endif
+}
+
+QVector3D QSoundSourcePrivate::velocity() const
+{
+ if (!m_alSource)
+ return QVector3D(0, 0, 0);
+ ALfloat x, y, z;
+ alGetSource3f(m_alSource, AL_VELOCITY, &x, &y, &z);
+ return QVector3D(x, y, z);
+}
+
+QVector3D QSoundSourcePrivate::position() const
+{
+ if (!m_alSource)
+ return QVector3D(0, 0, 0);
+ ALfloat x, y, z;
+ alGetSource3f(m_alSource, AL_POSITION, &x, &y, &z);
+ return QVector3D(x, y, z);
+}
+
+QVector3D QSoundSourcePrivate::direction() const
+{
+ if (!m_alSource)
+ return QVector3D(0, 1, 0);
+ ALfloat x, y, z;
+ alGetSource3f(m_alSource, AL_DIRECTION, &x, &y, &z);
+ return QVector3D(x, y, z);
+}
+
+void QSoundSourcePrivate::setGain(qreal gain)
+{
+ if (!m_alSource || gain == m_gain)
+ return;
+ alSourcef(m_alSource, AL_GAIN, gain);
+#ifdef DEBUG_AUDIOENGINE
+ QAudioEnginePrivate::checkNoError("source set gain");
+#endif
+ m_gain = gain;
+}
+
+void QSoundSourcePrivate::setPitch(qreal pitch)
+{
+ if (!m_alSource || m_pitch == pitch)
+ return;
+ alSourcef(m_alSource, AL_PITCH, pitch);
+#ifdef DEBUG_AUDIOENGINE
+ QAudioEnginePrivate::checkNoError("source set pitch");
+#endif
+ m_pitch = pitch;
+}
+
+void QSoundSourcePrivate::setCone(qreal innerAngle, qreal outerAngle, qreal outerGain)
+{
+ if (innerAngle > outerAngle)
+ outerAngle = innerAngle;
+ Q_ASSERT(outerAngle <= 360 && innerAngle >= 0);
+
+ //make sure the setting order will always keep outerAngle >= innerAngle in openAL
+ if (outerAngle >= m_coneInnerAngle) {
+ if (m_coneOuterAngle != outerAngle) {
+ alSourcef(m_alSource, AL_CONE_OUTER_ANGLE, outerAngle);
+#ifdef DEBUG_AUDIOENGINE
+ QAudioEnginePrivate::checkNoError("source set cone outerAngle");
+#endif
+ m_coneOuterAngle = outerAngle;
+ }
+ if (m_coneInnerAngle != innerAngle) {
+ alSourcef(m_alSource, AL_CONE_INNER_ANGLE, innerAngle);
+#ifdef DEBUG_AUDIOENGINE
+ QAudioEnginePrivate::checkNoError("source set cone innerAngle");
+#endif
+ m_coneInnerAngle = innerAngle;
+ }
+ } else {
+ if (m_coneInnerAngle != innerAngle) {
+ alSourcef(m_alSource, AL_CONE_INNER_ANGLE, innerAngle);
+#ifdef DEBUG_AUDIOENGINE
+ QAudioEnginePrivate::checkNoError("source set cone innerAngle");
+#endif
+ m_coneInnerAngle = innerAngle;
+ }
+ if (m_coneOuterAngle != outerAngle) {
+ alSourcef(m_alSource, AL_CONE_OUTER_ANGLE, outerAngle);
+#ifdef DEBUG_AUDIOENGINE
+ QAudioEnginePrivate::checkNoError("source set cone outerAngle");
+#endif
+ m_coneOuterAngle = outerAngle;
+ }
+ }
+
+ if (outerGain != m_coneOuterGain) {
+ alSourcef(m_alSource, AL_CONE_OUTER_GAIN, outerGain);
+#ifdef DEBUG_AUDIOENGINE
+ QAudioEnginePrivate::checkNoError("source set cone outerGain");
+#endif
+ m_coneOuterGain = outerGain;
+ }
+}
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 QSOUNDSOURCE_P_H
+#define QSOUNDSOURCE_P_H
+
+#include <QVector3D>
+#include <QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSoundBuffer;
+
+class QSoundSource : public QObject
+{
+ Q_OBJECT
+public:
+ enum State
+ {
+ StoppedState,
+ PlayingState,
+ PausedState
+ };
+
+ virtual void play() = 0;
+ virtual void pause() = 0;
+ virtual void stop() = 0;
+
+ virtual QSoundSource::State state() const = 0;
+
+ virtual void setLooping(bool looping) = 0;
+ virtual void setDirection(const QVector3D& direction) = 0;
+ virtual void setPosition(const QVector3D& position) = 0;
+ virtual void setVelocity(const QVector3D& velocity) = 0;
+
+ virtual QVector3D velocity() const = 0;
+ virtual QVector3D position() const = 0;
+ virtual QVector3D direction() const = 0;
+
+ virtual void setGain(qreal gain) = 0;
+ virtual void setPitch(qreal pitch) = 0;
+ virtual void setCone(qreal innerAngle, qreal outerAngle, qreal outerGain) = 0;
+
+ virtual void bindBuffer(QSoundBuffer*) = 0;
+ virtual void unbindBuffer() = 0;
+
+Q_SIGNALS:
+ void stateChanged(QSoundSource::State newState);
+
+protected:
+ QSoundSource(QObject *parent);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
-
TEMPLATE = subdirs
SUBDIRS += multimedia
+contains(config_test_openal, yes): SUBDIRS += audioengine
\endcode
*/
-QSampleCache::QSampleCache()
- : m_networkAccessManager(0)
+QSampleCache::QSampleCache(QObject *parent)
+ : QObject(parent)
+ , m_networkAccessManager(0)
, m_mutex(QMutex::Recursive)
, m_capacity(0)
, m_usage(0)
+ , m_loadingRefCount(0)
{
m_loadingThread.setObjectName(QLatin1String("QSampleCache::LoadingThread"));
+ connect(&m_loadingThread, SIGNAL(finished()), this, SIGNAL(isLoadingChanged()));
+ connect(&m_loadingThread, SIGNAL(started()), this, SIGNAL(isLoadingChanged()));
}
QNetworkAccessManager& QSampleCache::networkAccessManager()
delete m_networkAccessManager;
}
+void QSampleCache::loadingRelease()
+{
+ QMutexLocker locker(&m_loadingMutex);
+ m_loadingRefCount--;
+ if (m_loadingRefCount == 0) {
+ if (m_loadingThread.isRunning())
+ m_loadingThread.exit();
+ }
+}
+
+bool QSampleCache::isLoading() const
+{
+ return m_loadingThread.isRunning();
+}
+
QSample* QSampleCache::requestSample(const QUrl& url)
{
+ //lock and add first to make sure live loadingThread will not be killed during this function call
+ m_loadingMutex.lock();
+ m_loadingRefCount++;
+ m_loadingMutex.unlock();
+
if (!m_loadingThread.isRunning())
m_loadingThread.start();
+
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "QSampleCache: request sample [" << url << "]";
#endif
if (m_state == QSample::Error || m_state == QSample::Creating) {
m_state = QSample::Loading;
QMetaObject::invokeMethod(this, "load", Qt::QueuedConnection);
+ } else {
+ qobject_cast<QSampleCache*>(m_parent)->loadingRelease();
}
}
#endif
cleanup();
m_state = QSample::Error;
+ qobject_cast<QSampleCache*>(m_parent)->loadingRelease();
emit error();
}
m_audioFormat = m_waveDecoder->audioFormat();
cleanup();
m_state = QSample::Ready;
+ qobject_cast<QSampleCache*>(m_parent)->loadingRelease();
emit ready();
}
class QWaveDecoder;
// Lives in application thread
-class QSample : public QObject
+class Q_MULTIMEDIA_EXPORT QSample : public QObject
{
Q_OBJECT
public:
int m_ref;
};
-class QSampleCache
+class Q_MULTIMEDIA_EXPORT QSampleCache : public QObject
{
+ Q_OBJECT
public:
friend class QSample;
- QSampleCache();
+ QSampleCache(QObject *parent = 0);
~QSampleCache();
QSample* requestSample(const QUrl& url);
void setCapacity(qint64 capacity);
+ bool isLoading() const;
+
+Q_SIGNALS:
+ void isLoadingChanged();
+
private:
QMap<QUrl, QSample*> m_samples;
QSet<QSample*> m_staleSamples;
bool notifyUnreferencedSample(QSample* sample);
void removeUnreferencedSample(QSample* sample);
void unloadSample(QSample* sample);
+
+ void loadingRelease();
+ int m_loadingRefCount;
+ QMutex m_loadingMutex;
};
QT_END_NAMESPACE
"pulseaudio" => {},
"resourcepolicy" => {},
"xvideo" => {},
+
+ "openal" => {},
);