Add AudioEngine with new implementation
authorLing Hu <ling.hu@nokia.com>
Wed, 18 Jan 2012 07:17:54 +0000 (17:17 +1000)
committerQt by Nokia <qt-info@nokia.com>
Mon, 6 Feb 2012 04:35:28 +0000 (05:35 +0100)
Change-Id: I5eebe662ecbce9814ed3e763db56df9be737d11f
Reviewed-by: Michael Goddard <michael.goddard@nokia.com>
39 files changed:
config.tests/openal/main.cpp [new file with mode: 0644]
config.tests/openal/openal.pro [new file with mode: 0644]
examples/audioengine/audioengine.pro [new file with mode: 0644]
examples/audioengine/qml/audioengine.qml [new file with mode: 0644]
examples/audioengine/qml/audioengine.qmlproject [new file with mode: 0644]
examples/audioengine/qml/content/MyAudioEngine.qml [new file with mode: 0644]
examples/examples.pro
src/imports/audioengine/audioengine.cpp [new file with mode: 0644]
src/imports/audioengine/audioengine.pro [new file with mode: 0644]
src/imports/audioengine/qaudioengine_openal_p.cpp [new file with mode: 0644]
src/imports/audioengine/qaudioengine_openal_p.h [new file with mode: 0644]
src/imports/audioengine/qaudioengine_p.cpp [new file with mode: 0644]
src/imports/audioengine/qaudioengine_p.h [new file with mode: 0644]
src/imports/audioengine/qdeclarative_attenuationmodel_p.cpp [new file with mode: 0644]
src/imports/audioengine/qdeclarative_attenuationmodel_p.h [new file with mode: 0644]
src/imports/audioengine/qdeclarative_audiocategory_p.cpp [new file with mode: 0644]
src/imports/audioengine/qdeclarative_audiocategory_p.h [new file with mode: 0644]
src/imports/audioengine/qdeclarative_audioengine_p.cpp [new file with mode: 0644]
src/imports/audioengine/qdeclarative_audioengine_p.h [new file with mode: 0644]
src/imports/audioengine/qdeclarative_audiolistener_p.cpp [new file with mode: 0644]
src/imports/audioengine/qdeclarative_audiolistener_p.h [new file with mode: 0644]
src/imports/audioengine/qdeclarative_audiosample_p.cpp [new file with mode: 0644]
src/imports/audioengine/qdeclarative_audiosample_p.h [new file with mode: 0644]
src/imports/audioengine/qdeclarative_playvariation_p.cpp [new file with mode: 0644]
src/imports/audioengine/qdeclarative_playvariation_p.h [new file with mode: 0644]
src/imports/audioengine/qdeclarative_sound_p.cpp [new file with mode: 0644]
src/imports/audioengine/qdeclarative_sound_p.h [new file with mode: 0644]
src/imports/audioengine/qdeclarative_soundinstance_p.cpp [new file with mode: 0644]
src/imports/audioengine/qdeclarative_soundinstance_p.h [new file with mode: 0644]
src/imports/audioengine/qmldir [new file with mode: 0644]
src/imports/audioengine/qsoundbuffer_p.h [new file with mode: 0644]
src/imports/audioengine/qsoundinstance_p.cpp [new file with mode: 0644]
src/imports/audioengine/qsoundinstance_p.h [new file with mode: 0644]
src/imports/audioengine/qsoundsource_openal_p.cpp [new file with mode: 0644]
src/imports/audioengine/qsoundsource_p.h [new file with mode: 0644]
src/imports/imports.pro
src/multimedia/audio/qsamplecache_p.cpp
src/multimedia/audio/qsamplecache_p.h
sync.profile

diff --git a/config.tests/openal/main.cpp b/config.tests/openal/main.cpp
new file mode 100644 (file)
index 0000000..6953062
--- /dev/null
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** 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;
+}
diff --git a/config.tests/openal/openal.pro b/config.tests/openal/openal.pro
new file mode 100644 (file)
index 0000000..58ce529
--- /dev/null
@@ -0,0 +1,11 @@
+TEMPLATE = app
+DEPENDPATH += .
+INCLUDEPATH += .
+
+SOURCES += main.cpp
+
+win32 {
+    LIBS += -lOpenAL32
+}else {
+    LIBS += -lopenal
+}
diff --git a/examples/audioengine/audioengine.pro b/examples/audioengine/audioengine.pro
new file mode 100644 (file)
index 0000000..d054115
--- /dev/null
@@ -0,0 +1,7 @@
+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
diff --git a/examples/audioengine/qml/audioengine.qml b/examples/audioengine/qml/audioengine.qml
new file mode 100644 (file)
index 0000000..7b1980a
--- /dev/null
@@ -0,0 +1,193 @@
+/****************************************************************************
+ **
+ ** 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
+        }
+    }
+}
diff --git a/examples/audioengine/qml/audioengine.qmlproject b/examples/audioengine/qml/audioengine.qmlproject
new file mode 100644 (file)
index 0000000..15b002b
--- /dev/null
@@ -0,0 +1,16 @@
+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: "."
+    }
+}
diff --git a/examples/audioengine/qml/content/MyAudioEngine.qml b/examples/audioengine/qml/content/MyAudioEngine.qml
new file mode 100644 (file)
index 0000000..219485f
--- /dev/null
@@ -0,0 +1,131 @@
+/****************************************************************************
+ **
+ ** 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"
+}
index 3f2aaca..164200f 100644 (file)
@@ -24,3 +24,4 @@ TEMPLATE = subdirs
     QT += widgets
 }
 
+contains(config_test_openal, yes): SUBDIRS += audioengine
diff --git a/src/imports/audioengine/audioengine.cpp b/src/imports/audioengine/audioengine.cpp
new file mode 100644 (file)
index 0000000..495a11a
--- /dev/null
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** 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));
+
diff --git a/src/imports/audioengine/audioengine.pro b/src/imports/audioengine/audioengine.pro
new file mode 100644 (file)
index 0000000..d3cc2ba
--- /dev/null
@@ -0,0 +1,51 @@
+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
diff --git a/src/imports/audioengine/qaudioengine_openal_p.cpp b/src/imports/audioengine/qaudioengine_openal_p.cpp
new file mode 100644 (file)
index 0000000..4818cf5
--- /dev/null
@@ -0,0 +1,448 @@
+/****************************************************************************
+**
+** 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"
diff --git a/src/imports/audioengine/qaudioengine_openal_p.h b/src/imports/audioengine/qaudioengine_openal_p.h
new file mode 100644 (file)
index 0000000..bac6218
--- /dev/null
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** 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
diff --git a/src/imports/audioengine/qaudioengine_p.cpp b/src/imports/audioengine/qaudioengine_p.cpp
new file mode 100644 (file)
index 0000000..0c23910
--- /dev/null
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** 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);
+}
diff --git a/src/imports/audioengine/qaudioengine_p.h b/src/imports/audioengine/qaudioengine_p.h
new file mode 100644 (file)
index 0000000..12b5bbd
--- /dev/null
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** 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
diff --git a/src/imports/audioengine/qdeclarative_attenuationmodel_p.cpp b/src/imports/audioengine/qdeclarative_attenuationmodel_p.cpp
new file mode 100644 (file)
index 0000000..6624773
--- /dev/null
@@ -0,0 +1,379 @@
+/****************************************************************************
+**
+** 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);
+}
+
diff --git a/src/imports/audioengine/qdeclarative_attenuationmodel_p.h b/src/imports/audioengine/qdeclarative_attenuationmodel_p.h
new file mode 100644 (file)
index 0000000..57b96fe
--- /dev/null
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** 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
diff --git a/src/imports/audioengine/qdeclarative_audiocategory_p.cpp b/src/imports/audioengine/qdeclarative_audiocategory_p.cpp
new file mode 100644 (file)
index 0000000..a7379c2
--- /dev/null
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** 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();
+}
diff --git a/src/imports/audioengine/qdeclarative_audiocategory_p.h b/src/imports/audioengine/qdeclarative_audiocategory_p.h
new file mode 100644 (file)
index 0000000..fa8eb51
--- /dev/null
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** 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
diff --git a/src/imports/audioengine/qdeclarative_audioengine_p.cpp b/src/imports/audioengine/qdeclarative_audioengine_p.cpp
new file mode 100644 (file)
index 0000000..a2763e0
--- /dev/null
@@ -0,0 +1,519 @@
+/****************************************************************************
+**
+** 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
+
diff --git a/src/imports/audioengine/qdeclarative_audioengine_p.h b/src/imports/audioengine/qdeclarative_audioengine_p.h
new file mode 100644 (file)
index 0000000..4b1364d
--- /dev/null
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** 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
diff --git a/src/imports/audioengine/qdeclarative_audiolistener_p.cpp b/src/imports/audioengine/qdeclarative_audiolistener_p.cpp
new file mode 100644 (file)
index 0000000..97c424f
--- /dev/null
@@ -0,0 +1,263 @@
+/****************************************************************************
+**
+** 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();
+}
diff --git a/src/imports/audioengine/qdeclarative_audiolistener_p.h b/src/imports/audioengine/qdeclarative_audiolistener_p.h
new file mode 100644 (file)
index 0000000..97f1e73
--- /dev/null
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** 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
diff --git a/src/imports/audioengine/qdeclarative_audiosample_p.cpp b/src/imports/audioengine/qdeclarative_audiosample_p.cpp
new file mode 100644 (file)
index 0000000..24a88ae
--- /dev/null
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** 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
+*/
+
+
diff --git a/src/imports/audioengine/qdeclarative_audiosample_p.h b/src/imports/audioengine/qdeclarative_audiosample_p.h
new file mode 100644 (file)
index 0000000..d854efd
--- /dev/null
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** 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
diff --git a/src/imports/audioengine/qdeclarative_playvariation_p.cpp b/src/imports/audioengine/qdeclarative_playvariation_p.cpp
new file mode 100644 (file)
index 0000000..ec06827
--- /dev/null
@@ -0,0 +1,287 @@
+/****************************************************************************
+**
+** 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);
+}
diff --git a/src/imports/audioengine/qdeclarative_playvariation_p.h b/src/imports/audioengine/qdeclarative_playvariation_p.h
new file mode 100644 (file)
index 0000000..1438aa5
--- /dev/null
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** 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
diff --git a/src/imports/audioengine/qdeclarative_sound_p.cpp b/src/imports/audioengine/qdeclarative_sound_p.cpp
new file mode 100644 (file)
index 0000000..3791273
--- /dev/null
@@ -0,0 +1,558 @@
+/****************************************************************************
+**
+** 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;
+}
+
diff --git a/src/imports/audioengine/qdeclarative_sound_p.h b/src/imports/audioengine/qdeclarative_sound_p.h
new file mode 100644 (file)
index 0000000..9784b04
--- /dev/null
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** 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
diff --git a/src/imports/audioengine/qdeclarative_soundinstance_p.cpp b/src/imports/audioengine/qdeclarative_soundinstance_p.cpp
new file mode 100644 (file)
index 0000000..4f3ade9
--- /dev/null
@@ -0,0 +1,560 @@
+/****************************************************************************
+**
+** 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
+*/
diff --git a/src/imports/audioengine/qdeclarative_soundinstance_p.h b/src/imports/audioengine/qdeclarative_soundinstance_p.h
new file mode 100644 (file)
index 0000000..0fd8c9a
--- /dev/null
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** 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
diff --git a/src/imports/audioengine/qmldir b/src/imports/audioengine/qmldir
new file mode 100644 (file)
index 0000000..94335c0
--- /dev/null
@@ -0,0 +1 @@
+plugin declarative_audioengine
diff --git a/src/imports/audioengine/qsoundbuffer_p.h b/src/imports/audioengine/qsoundbuffer_p.h
new file mode 100644 (file)
index 0000000..024fc62
--- /dev/null
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** 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
diff --git a/src/imports/audioengine/qsoundinstance_p.cpp b/src/imports/audioengine/qsoundinstance_p.cpp
new file mode 100644 (file)
index 0000000..9c5fc7a
--- /dev/null
@@ -0,0 +1,387 @@
+/****************************************************************************
+**
+** 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
diff --git a/src/imports/audioengine/qsoundinstance_p.h b/src/imports/audioengine/qsoundinstance_p.h
new file mode 100644 (file)
index 0000000..6278627
--- /dev/null
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** 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
diff --git a/src/imports/audioengine/qsoundsource_openal_p.cpp b/src/imports/audioengine/qsoundsource_openal_p.cpp
new file mode 100644 (file)
index 0000000..8f5bd19
--- /dev/null
@@ -0,0 +1,314 @@
+/****************************************************************************
+**
+** 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;
+    }
+}
diff --git a/src/imports/audioengine/qsoundsource_p.h b/src/imports/audioengine/qsoundsource_p.h
new file mode 100644 (file)
index 0000000..8f2fb63
--- /dev/null
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** 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
index 669064b..4439407 100644 (file)
@@ -1,5 +1,5 @@
-
 TEMPLATE = subdirs
 
 SUBDIRS += multimedia
+contains(config_test_openal, yes): SUBDIRS += audioengine
 
index aca0895..addc03d 100644 (file)
@@ -93,13 +93,17 @@ QT_BEGIN_NAMESPACE
     \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()
@@ -128,10 +132,31 @@ QSampleCache::~QSampleCache()
     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
@@ -250,6 +275,8 @@ void QSample::loadIfNecessary()
     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();
     }
 }
 
@@ -367,6 +394,7 @@ void QSample::decoderError()
 #endif
     cleanup();
     m_state = QSample::Error;
+    qobject_cast<QSampleCache*>(m_parent)->loadingRelease();
     emit error();
 }
 
@@ -380,6 +408,7 @@ void QSample::onReady()
     m_audioFormat = m_waveDecoder->audioFormat();
     cleanup();
     m_state = QSample::Ready;
+    qobject_cast<QSampleCache*>(m_parent)->loadingRelease();
     emit ready();
 }
 
index d5997b9..0c1bc5e 100644 (file)
@@ -74,7 +74,7 @@ class QSampleCache;
 class QWaveDecoder;
 
 // Lives in application thread
-class QSample : public QObject
+class Q_MULTIMEDIA_EXPORT QSample : public QObject
 {
     Q_OBJECT
 public:
@@ -127,17 +127,23 @@ private:
     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;
@@ -152,6 +158,10 @@ private:
     bool notifyUnreferencedSample(QSample* sample);
     void removeUnreferencedSample(QSample* sample);
     void unloadSample(QSample* sample);
+
+    void loadingRelease();
+    int m_loadingRefCount;
+    QMutex m_loadingMutex;
 };
 
 QT_END_NAMESPACE
index 31fff9e..46b32a0 100644 (file)
@@ -52,4 +52,6 @@
     "pulseaudio" => {},
     "resourcepolicy" => {},
     "xvideo" => {},
+
+    "openal" => {},
 );