diff options
author | Siteshwar Vashisht <siteshwar@gmail.com> | 2015-03-25 19:43:19 +0530 |
---|---|---|
committer | Konstantin Ritt <ritt.ks@gmail.com> | 2015-04-23 11:56:18 +0000 |
commit | 176d52bb28b425f697ad8df001ba2c7c52fda766 (patch) | |
tree | ffc4740404f9537bcef939acddb25c2cce4f7203 /src/imports/audioengine | |
parent | 227c8aa723d9e82c2826a1d2823cd73236f18bbb (diff) | |
download | qtmultimedia-176d52bb28b425f697ad8df001ba2c7c52fda766.tar.gz |
Refactored code for audio engine to allow dynamic object creation
QDeclarativeSound, QDeclarativeAudioSample, QDeclarativeAudioCategory
and QDeclarativeAttenuationModel can now be dynamically added to
AudioEngine instance or declared inside AudioEngine object definition.
QDeclarativePlayVariation can now be dynamically added to Sound
instance or declared inside Sound object definition.
Change-Id: If4c2e16895a71eb71ded1998c107360698f8ac7f
Reviewed-by: Yoann Lopes <yoann.lopes@theqtcompany.com>
Diffstat (limited to 'src/imports/audioengine')
13 files changed, 425 insertions, 229 deletions
diff --git a/src/imports/audioengine/audioengine.cpp b/src/imports/audioengine/audioengine.cpp index 612524447..4d29528f9 100644 --- a/src/imports/audioengine/audioengine.cpp +++ b/src/imports/audioengine/audioengine.cpp @@ -68,6 +68,10 @@ public: qmlRegisterType<QDeclarativeAttenuationModelLinear>(uri, 1, 0, "AttenuationModelLinear"); qmlRegisterType<QDeclarativeAttenuationModelInverse>(uri, 1, 0, "AttenuationModelInverse"); + + // Dynamically adding audio engine related objects is only supported through revision 1 + qmlRegisterRevision<QDeclarativeAudioEngine, 1>(uri, 1, 1); + qmlRegisterRevision<QDeclarativeSound, 1>(uri, 1, 1); } }; diff --git a/src/imports/audioengine/qdeclarative_attenuationmodel_p.cpp b/src/imports/audioengine/qdeclarative_attenuationmodel_p.cpp index 0814e9d62..7ecdb41ae 100644 --- a/src/imports/audioengine/qdeclarative_attenuationmodel_p.cpp +++ b/src/imports/audioengine/qdeclarative_attenuationmodel_p.cpp @@ -32,6 +32,7 @@ ****************************************************************************/ #include "qdeclarative_attenuationmodel_p.h" +#include "qdeclarative_audioengine_p.h" #include "qdebug.h" #define DEBUG_AUDIOENGINE @@ -40,7 +41,7 @@ QT_USE_NAMESPACE QDeclarativeAttenuationModel::QDeclarativeAttenuationModel(QObject *parent) : QObject(parent) - , m_complete(false) + , m_engine(0) { } @@ -48,22 +49,9 @@ QDeclarativeAttenuationModel::~QDeclarativeAttenuationModel() { } -void QDeclarativeAttenuationModel::classBegin() +void QDeclarativeAttenuationModel::setEngine(QDeclarativeAudioEngine *engine) { - 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; + m_engine = engine; } QString QDeclarativeAttenuationModel::name() const @@ -73,7 +61,7 @@ QString QDeclarativeAttenuationModel::name() const void QDeclarativeAttenuationModel::setName(const QString& name) { - if (m_complete) { + if (m_engine) { qWarning("AttenuationModel: you can not change name after initialization."); return; } @@ -93,7 +81,9 @@ void QDeclarativeAttenuationModel::setName(const QString& name) This type is part of the \b{QtAudioEngine 1.0} module. - AttenuationModelLinear must be defined inside \l AudioEngine. + AttenuationModelLinear must be defined inside \l AudioEngine or be added to it using + \l{QtAudioEngine::AudioEngine::addAttenuationModel()}{AudioEngine.addAttenuationModel()} + if AttenuationModelLinear is created dynamically. \qml import QtQuick 2.0 @@ -144,13 +134,13 @@ QDeclarativeAttenuationModelLinear::QDeclarativeAttenuationModelLinear(QObject * { } -void QDeclarativeAttenuationModelLinear::componentComplete() +void QDeclarativeAttenuationModelLinear::setEngine(QDeclarativeAudioEngine *engine) { if (m_start > m_end) { qSwap(m_start, m_end); qWarning() << "AttenuationModelLinear[" << m_name << "]: start must be less or equal than end."; } - QDeclarativeAttenuationModel::componentComplete(); + QDeclarativeAttenuationModel::setEngine(engine); } /*! @@ -167,7 +157,7 @@ qreal QDeclarativeAttenuationModelLinear::startDistance() const void QDeclarativeAttenuationModelLinear::setStartDistance(qreal startDist) { - if (m_complete) { + if (m_engine) { qWarning() << "AttenuationModelLinear[" << m_name << "]: you can not change properties after initialization."; return; } @@ -192,7 +182,7 @@ qreal QDeclarativeAttenuationModelLinear::endDistance() const void QDeclarativeAttenuationModelLinear::setEndDistance(qreal endDist) { - if (m_complete) { + if (m_engine) { qWarning() << "AttenuationModelLinear[" << m_name << "]: you can not change properties after initialization."; return; } @@ -226,7 +216,9 @@ qreal QDeclarativeAttenuationModelLinear::calculateGain(const QVector3D &listene This type is part of the \b{QtAudioEngine 1.0} module. - AttenuationModelInverse must be defined inside AudioEngine. + AttenuationModelInverse must be defined inside \l AudioEngine or be added to it using + \l{QtAudioEngine::AudioEngine::addAttenuationModel()}{AudioEngine.addAttenuationModel()} + if AttenuationModelInverse is created dynamically. \qml import QtQuick 2.0 @@ -309,13 +301,13 @@ QDeclarativeAttenuationModelInverse::QDeclarativeAttenuationModelInverse(QObject { } -void QDeclarativeAttenuationModelInverse::componentComplete() +void QDeclarativeAttenuationModelInverse::setEngine(QDeclarativeAudioEngine *engine) { if (m_ref > m_max) { qSwap(m_ref, m_max); qWarning() << "AttenuationModelInverse[" << m_name << "]: referenceDistance must be less or equal than maxDistance."; } - QDeclarativeAttenuationModel::componentComplete(); + QDeclarativeAttenuationModel::setEngine(engine); } qreal QDeclarativeAttenuationModelInverse::referenceDistance() const @@ -325,7 +317,7 @@ qreal QDeclarativeAttenuationModelInverse::referenceDistance() const void QDeclarativeAttenuationModelInverse::setReferenceDistance(qreal referenceDistance) { - if (m_complete) { + if (m_engine) { qWarning() << "AttenuationModelInverse[" << m_name << "]: you can not change properties after initialization."; return; } @@ -343,7 +335,7 @@ qreal QDeclarativeAttenuationModelInverse::maxDistance() const void QDeclarativeAttenuationModelInverse::setMaxDistance(qreal maxDistance) { - if (m_complete) { + if (m_engine) { qWarning() << "AttenuationModelInverse[" << m_name << "]: you can not change properties after initialization."; return; } @@ -361,7 +353,7 @@ qreal QDeclarativeAttenuationModelInverse::rolloffFactor() const void QDeclarativeAttenuationModelInverse::setRolloffFactor(qreal rolloffFactor) { - if (m_complete) { + if (m_engine) { qWarning() << "AttenuationModelInverse[" << m_name << "]: you can not change properties after initialization."; return; } diff --git a/src/imports/audioengine/qdeclarative_attenuationmodel_p.h b/src/imports/audioengine/qdeclarative_attenuationmodel_p.h index dc8bff36f..f276757de 100644 --- a/src/imports/audioengine/qdeclarative_attenuationmodel_p.h +++ b/src/imports/audioengine/qdeclarative_attenuationmodel_p.h @@ -35,32 +35,31 @@ #define QDECLARATIVEATTENUATIONMODEL_P_H #include <QtQml/qqml.h> -#include <QtQml/qqmlcomponent.h> #include <QVector3D> QT_BEGIN_NAMESPACE -class QDeclarativeAttenuationModel : public QObject, public QQmlParserStatus +class QDeclarativeAudioEngine; + +class QDeclarativeAttenuationModel : public QObject { Q_OBJECT - Q_INTERFACES(QQmlParserStatus) 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; + virtual void setEngine(QDeclarativeAudioEngine *engine); + protected: - bool m_complete; QString m_name; + QDeclarativeAudioEngine *m_engine; private: Q_DISABLE_COPY(QDeclarativeAttenuationModel); @@ -75,8 +74,6 @@ class QDeclarativeAttenuationModelLinear : public QDeclarativeAttenuationModel public: QDeclarativeAttenuationModelLinear(QObject *parent = 0); - void componentComplete(); - qreal startDistance() const; void setStartDistance(qreal startDist); @@ -85,6 +82,8 @@ public: qreal calculateGain(const QVector3D &listenerPosition, const QVector3D &sourcePosition) const; + void setEngine(QDeclarativeAudioEngine *engine); + private: Q_DISABLE_COPY(QDeclarativeAttenuationModelLinear); qreal m_start; @@ -101,8 +100,6 @@ class QDeclarativeAttenuationModelInverse : public QDeclarativeAttenuationModel public: QDeclarativeAttenuationModelInverse(QObject *parent = 0); - void componentComplete(); - qreal referenceDistance() const; void setReferenceDistance(qreal referenceDistance); @@ -114,6 +111,8 @@ public: qreal calculateGain(const QVector3D &listenerPosition, const QVector3D &sourcePosition) const; + void setEngine(QDeclarativeAudioEngine *engine); + private: Q_DISABLE_COPY(QDeclarativeAttenuationModelInverse); qreal m_ref; diff --git a/src/imports/audioengine/qdeclarative_audiocategory_p.cpp b/src/imports/audioengine/qdeclarative_audiocategory_p.cpp index df1a3cec9..847941ca9 100644 --- a/src/imports/audioengine/qdeclarative_audiocategory_p.cpp +++ b/src/imports/audioengine/qdeclarative_audiocategory_p.cpp @@ -51,7 +51,9 @@ QT_USE_NAMESPACE This type is part of the \b{QtAudioEngine 1.0} module. An instance of AudioCategory can be accessed through \l {QtAudioEngine::AudioEngine::categories} - {AudioEngine.categories} with its unique name and must be defined inside AudioEngine. + {AudioEngine.categories} with its unique name and must be defined inside AudioEngine or be added + to it using \l{QtAudioEngine::AudioEngine::addAudioCategory()}{AudioEngine.addAudioCategory()} if + AudioCategory is created dynamically. \qml import QtQuick 2.0 @@ -103,8 +105,8 @@ QT_USE_NAMESPACE */ QDeclarativeAudioCategory::QDeclarativeAudioCategory(QObject *parent) : QObject(parent) - , m_complete(false) , m_volume(1) + , m_engine(0) { } @@ -112,21 +114,9 @@ QDeclarativeAudioCategory::~QDeclarativeAudioCategory() { } -void QDeclarativeAudioCategory::classBegin() +void QDeclarativeAudioCategory::setEngine(QDeclarativeAudioEngine *engine) { - 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; + m_engine = engine; } /*! @@ -159,7 +149,7 @@ void QDeclarativeAudioCategory::setVolume(qreal volume) */ void QDeclarativeAudioCategory::setName(const QString& name) { - if (m_complete) { + if (m_engine) { qWarning("AudioCategory: you can not change name after initialization."); return; } diff --git a/src/imports/audioengine/qdeclarative_audiocategory_p.h b/src/imports/audioengine/qdeclarative_audiocategory_p.h index a797b2698..0345edfdb 100644 --- a/src/imports/audioengine/qdeclarative_audiocategory_p.h +++ b/src/imports/audioengine/qdeclarative_audiocategory_p.h @@ -35,14 +35,14 @@ #define QDECLARATIVEAUDIOCATEGORY_P_H #include <QtQml/qqml.h> -#include <QtQml/qqmlcomponent.h> QT_BEGIN_NAMESPACE -class QDeclarativeAudioCategory : public QObject, public QQmlParserStatus +class QDeclarativeAudioEngine; + +class QDeclarativeAudioCategory : public QObject { Q_OBJECT - Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(qreal volume READ volume WRITE setVolume NOTIFY volumeChanged) Q_PROPERTY(QString name READ name WRITE setName) @@ -50,15 +50,14 @@ 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); + void setEngine(QDeclarativeAudioEngine *engine); + Q_SIGNALS: void volumeChanged(qreal newVolume); void stopped(); @@ -72,9 +71,9 @@ public Q_SLOTS: private: Q_DISABLE_COPY(QDeclarativeAudioCategory); - bool m_complete; QString m_name; qreal m_volume; + QDeclarativeAudioEngine *m_engine; }; QT_END_NAMESPACE diff --git a/src/imports/audioengine/qdeclarative_audioengine_p.cpp b/src/imports/audioengine/qdeclarative_audioengine_p.cpp index cf0a22644..dd80c698d 100644 --- a/src/imports/audioengine/qdeclarative_audioengine_p.cpp +++ b/src/imports/audioengine/qdeclarative_audioengine_p.cpp @@ -221,6 +221,222 @@ void QDeclarativeAudioEngine::releaseSoundInstance(QSoundInstance* instance) emit liveInstanceCountChanged(); } +void QDeclarativeAudioEngine::initAudioSample(QDeclarativeAudioSample *sample) +{ + sample->init(); +} + +void QDeclarativeAudioEngine::initSound(QDeclarativeSound *sound) +{ + 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"; + } + } +} + +/*! + \qmlmethod QtAudioEngine::AudioEngine::addAudioSample(AudioSample sample) + + Adds the given \a sample to the engine. + This can be used when the AudioSample is created dynamically: + + \qml + import QtAudioEngine 1.1 + + AudioEngine { + id: engine + + Component.onCompleted: { + var sample = Qt.createQmlObject('import QtAudioEngine 1.1; AudioSample {}', engine); + sample.name = "example"; + sample.source = "example.wav"; + engine.addAudioSample(sample); + } + } + \endqml +*/ +void QDeclarativeAudioEngine::addAudioSample(QDeclarativeAudioSample *sample) +{ +#ifdef DEBUG_AUDIOENGINE + qDebug() << "add QDeclarativeAudioSample[" << sample->name() << "]"; +#endif + if (sample->name().isEmpty()) { + qWarning("AudioSample must have a name!"); + return; + } + + if (m_samples.contains(sample->name())) { + qWarning() << "Failed to add AudioSample[" << sample->name() << "], already exists!"; + return; + } + m_samples.insert(sample->name(), QVariant::fromValue(sample)); + sample->setEngine(this); + + if (m_complete) { initAudioSample(sample); } +} + +/*! + \qmlmethod QtAudioEngine::AudioEngine::addSound(Sound sound) + + Adds the given \a sound to the engine. + This can be used when the Sound is created dynamically: + + \qml + import QtAudioEngine 1.1 + + AudioEngine { + id: engine + + Component.onCompleted: { + var sound = Qt.createQmlObject('import QtAudioEngine 1.1; Sound {}', engine); + sound.name = "example"; + engine.addSound(sound); + } + } + \endqml +*/ +void QDeclarativeAudioEngine::addSound(QDeclarativeSound *sound) +{ +#ifdef DEBUG_AUDIOENGINE + qDebug() << "add QDeclarativeSound[" << sound->name() << "]"; +#endif + if (sound->name().isEmpty()) { + qWarning("Sound must have a name!"); + return; + } + + if (m_sounds.contains(sound->name())) { + qWarning() << "Failed to add Sound[" << sound->name() << "], already exists!"; + return; + } + m_sounds.insert(sound->name(), QVariant::fromValue(sound)); + sound->setEngine(this); + + if (m_complete) { initSound(sound); } + +} + +/*! + \qmlmethod QtAudioEngine::AudioEngine::addAudioCategory(AudioCategory category) + + Adds the given \a category to the engine. + This can be used when the AudioCategory is created dynamically: + + \qml + import QtAudioEngine 1.1 + + AudioEngine { + id: engine + + Component.onCompleted: { + var category = Qt.createQmlObject('import QtAudioEngine 1.1; AudioCategory {}', engine); + category.name = "sample"; + category.volume = 0.9; + engine.addAudioCategory(category); + } + } + \endqml +*/ +void QDeclarativeAudioEngine::addAudioCategory(QDeclarativeAudioCategory *category) +{ +#ifdef DEBUG_AUDIOENGINE + qDebug() << "add QDeclarativeAudioCategory[" << category->name() << "]"; +#endif + if (category->name().isEmpty()) { + qWarning("AudioCategory must have a name!"); + return; + } + + if (m_categories.contains(category->name())) { + qWarning() << "Failed to add AudioCategory[" << category->name() << "], already exists!"; + return; + } + m_categories.insert(category->name(), QVariant::fromValue(category)); + if (category->name() == QLatin1String("default")) { + if (!m_complete) { + m_defaultCategory = category; + } else { + qWarning() << "Can not change default category after initializing engine"; + } + } + + category->setEngine(this); +} + +/*! + \qmlmethod QtAudioEngine::AudioEngine::addAttenuationModel(AttenuationModel attenuationModel) + + Adds the given \a attenuationModel to the engine. + This can be used when the AttenuationModelLinear / AttenuationModelInverse is created dynamically: + + \qml + import QtAudioEngine 1.1 + + AudioEngine { + id: engine + + Component.onCompleted: { + var attenuationModel = Qt.createQmlObject('import QtAudioEngine 1.1; AttenuationModelLinear {}', engine); + attenuationModel.name ="linear" + attenuationModel.start = 20 + attenuationModel.end = 180 + engine.addAttenuationModel(attenuationModel); + } + } + \endqml +*/ +void QDeclarativeAudioEngine::addAttenuationModel(QDeclarativeAttenuationModel *attenModel) +{ +#ifdef DEBUG_AUDIOENGINE + qDebug() << "add AttenuationModel[" << attenModel->name() << "]"; +#endif + if (attenModel->name().isEmpty()) { + qWarning("AttenuationModel must have a name!"); + return; + } + + if (m_attenuationModels.contains(attenModel->name())) { + qWarning() << "Failed to add AttenuationModel[" << attenModel->name() << "], already exists!"; + return; + } + m_attenuationModels.insert(attenModel->name(), attenModel); + + if (attenModel->name() == QLatin1String("default")) { + if (!m_complete) { + m_defaultAttenuationModel = attenModel; + } else { + qWarning() << "Can not change default attenuation model after initializing engine"; + } + } + + attenModel->setEngine(this); +} + void QDeclarativeAudioEngine::componentComplete() { #ifdef DEBUG_AUDIOENGINE @@ -231,10 +447,9 @@ void QDeclarativeAudioEngine::componentComplete() 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(); + m_defaultCategory->setEngine(this); } #ifdef DEBUG_AUDIOENGINE qDebug() << "init samples" << m_samples.keys().count(); @@ -246,7 +461,8 @@ void QDeclarativeAudioEngine::componentComplete() qWarning() << "accessing invalid sample[" << key << "]"; continue; } - sample->init(); + + initAudioSample(sample); } #ifdef DEBUG_AUDIOENGINE @@ -260,35 +476,8 @@ void QDeclarativeAudioEngine::componentComplete() 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"; - } - } + + initSound(sound); } m_complete = true; #ifdef DEBUG_AUDIOENGINE @@ -330,65 +519,30 @@ void QDeclarativeAudioEngine::appendFunction(QQmlListProperty<QObject> *property { 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)); + engine->addSound(sound); 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)); + engine->addAudioSample(sample); 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; - } + engine->addAudioCategory(category); return; } 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); + engine->addAttenuationModel(attenModel); return; } diff --git a/src/imports/audioengine/qdeclarative_audioengine_p.h b/src/imports/audioengine/qdeclarative_audioengine_p.h index 51090b5dc..7ae6049f0 100644 --- a/src/imports/audioengine/qdeclarative_audioengine_p.h +++ b/src/imports/audioengine/qdeclarative_audioengine_p.h @@ -111,6 +111,11 @@ public: QSoundInstance* newSoundInstance(const QString &name); void releaseSoundInstance(QSoundInstance* instance); + Q_REVISION(1) Q_INVOKABLE void addAudioSample(QDeclarativeAudioSample *); + Q_REVISION(1) Q_INVOKABLE void addSound(QDeclarativeSound *); + Q_REVISION(1) Q_INVOKABLE void addAudioCategory(QDeclarativeAudioCategory *); + Q_REVISION(1) Q_INVOKABLE void addAttenuationModel(QDeclarativeAttenuationModel *); + Q_SIGNALS: void ready(); void liveInstanceCountChanged(); @@ -149,6 +154,9 @@ private: QList<QDeclarativeSoundInstance*> m_managedDeclSoundInstances; QList<QDeclarativeSoundInstance*> m_managedDeclSndInstancePool; void releaseManagedDeclarativeSoundInstance(QDeclarativeSoundInstance* declSndInstance); + + void initAudioSample(QDeclarativeAudioSample *); + void initSound(QDeclarativeSound *); }; QT_END_NAMESPACE diff --git a/src/imports/audioengine/qdeclarative_audiosample_p.cpp b/src/imports/audioengine/qdeclarative_audiosample_p.cpp index 5a9a67b71..297af3b31 100644 --- a/src/imports/audioengine/qdeclarative_audiosample_p.cpp +++ b/src/imports/audioengine/qdeclarative_audiosample_p.cpp @@ -54,7 +54,9 @@ QT_USE_NAMESPACE \c AudioSample is part of the \b{QtAudioEngine 1.0} module. It can be accessed through QtAudioEngine::AudioEngine::samples with its unique - name and must be defined inside AudioEngine. + name and must be defined inside AudioEngine or be added to it using + \l{QtAudioEngine::AudioEngine::addAudioSample()}{AudioEngine.addAudioSample()} + if AudioSample is created dynamically. \qml import QtQuick 2.0 @@ -78,10 +80,10 @@ QT_USE_NAMESPACE */ QDeclarativeAudioSample::QDeclarativeAudioSample(QObject *parent) : QObject(parent) - , m_complete(false) , m_streaming(false) , m_preloaded(false) , m_soundBuffer(0) + , m_engine(0) { } @@ -89,23 +91,6 @@ 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; -} - /*! \qmlproperty url QtAudioEngine::AudioSample::source @@ -118,7 +103,7 @@ QUrl QDeclarativeAudioSample::source() const void QDeclarativeAudioSample::setSource(const QUrl& url) { - if (m_complete) { + if (m_engine) { qWarning("AudioSample: source not changeable after initialization."); return; } @@ -130,6 +115,11 @@ bool QDeclarativeAudioSample::isStreaming() const return m_streaming; } +QDeclarativeAudioEngine *QDeclarativeAudioSample::engine() const +{ + return m_engine; +} + /*! \qmlproperty bool QtAudioEngine::AudioSample::preloaded @@ -173,7 +163,7 @@ void QDeclarativeAudioSample::load() void QDeclarativeAudioSample::setPreloaded(bool preloaded) { - if (m_complete) { + if (m_engine) { qWarning("AudioSample: preloaded not changeable after initialization."); return; } @@ -182,13 +172,22 @@ void QDeclarativeAudioSample::setPreloaded(bool preloaded) void QDeclarativeAudioSample::setStreaming(bool streaming) { - if (m_complete) { + if (m_engine) { qWarning("AudioSample: streaming not changeable after initialization."); return; } m_streaming = streaming; } +void QDeclarativeAudioSample::setEngine(QDeclarativeAudioEngine *engine) +{ + if (m_engine) { + qWarning("AudioSample: engine not changeable after initialization."); + return; + } + m_engine = engine; +} + /*! \qmlproperty string QtAudioEngine::AudioSample::name @@ -202,7 +201,7 @@ QString QDeclarativeAudioSample::name() const void QDeclarativeAudioSample::setName(const QString& name) { - if (m_complete) { + if (m_engine) { qWarning("AudioSample: name not changeable after initialization."); return; } @@ -211,12 +210,13 @@ void QDeclarativeAudioSample::setName(const QString& name) void QDeclarativeAudioSample::init() { + Q_ASSERT(m_engine != 0); + if (m_streaming) { //TODO } else { - m_soundBuffer = - qobject_cast<QDeclarativeAudioEngine*>(parent())->engine()->getStaticSoundBuffer(m_url); + m_soundBuffer = m_engine->engine()->getStaticSoundBuffer(m_url); if (m_soundBuffer->state() == QSoundBuffer::Ready) { emit loadedChanged(); } else { diff --git a/src/imports/audioengine/qdeclarative_audiosample_p.h b/src/imports/audioengine/qdeclarative_audiosample_p.h index 94e1c7e27..5b549e785 100644 --- a/src/imports/audioengine/qdeclarative_audiosample_p.h +++ b/src/imports/audioengine/qdeclarative_audiosample_p.h @@ -35,16 +35,15 @@ #define QDECLARATIVEAUDIOSAMPLE_P_H #include <QtQml/qqml.h> -#include <QtQml/qqmlcomponent.h> QT_BEGIN_NAMESPACE class QSoundBuffer; +class QDeclarativeAudioEngine; -class QDeclarativeAudioSample : public QObject, public QQmlParserStatus +class QDeclarativeAudioSample : public QObject { Q_OBJECT - Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QString name READ name WRITE setName) Q_PROPERTY(QUrl source READ source WRITE setSource) Q_PROPERTY(bool preloaded READ isPreloaded WRITE setPreloaded) @@ -55,9 +54,6 @@ public: QDeclarativeAudioSample(QObject *parent = 0); ~QDeclarativeAudioSample(); - void classBegin(); - void componentComplete(); - QString name() const; void setName(const QString& name); @@ -70,6 +66,9 @@ public: bool isPreloaded() const; void setPreloaded(bool preloaded); + QDeclarativeAudioEngine *engine() const; + void setEngine(QDeclarativeAudioEngine *); + bool isLoaded() const; QSoundBuffer* soundBuffer() const; @@ -85,13 +84,12 @@ public Q_SLOTS: private: Q_DISABLE_COPY(QDeclarativeAudioSample); - bool m_complete; QString m_name; QUrl m_url; bool m_streaming; bool m_preloaded; - QSoundBuffer *m_soundBuffer; + QDeclarativeAudioEngine *m_engine; }; QT_END_NAMESPACE diff --git a/src/imports/audioengine/qdeclarative_playvariation_p.cpp b/src/imports/audioengine/qdeclarative_playvariation_p.cpp index 38876c227..156f83f68 100644 --- a/src/imports/audioengine/qdeclarative_playvariation_p.cpp +++ b/src/imports/audioengine/qdeclarative_playvariation_p.cpp @@ -55,7 +55,9 @@ QT_USE_NAMESPACE This type is part of the \b{QtAudioEngine 1.0} module. - PlayVariation must be defined inside a \l Sound. + PlayVariation must be defined inside a \l Sound or be added to it using + \l{QtAudioEngine::Sound::addPlayVariation()}{Sound.addPlayVariation()} + if PlayVariation is created dynamically. \qml import QtQuick 2.0 @@ -100,13 +102,13 @@ QT_USE_NAMESPACE */ 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) + , m_engine(0) { } @@ -114,15 +116,7 @@ QDeclarativePlayVariation::~QDeclarativePlayVariation() { } -void QDeclarativePlayVariation::classBegin() -{ - if (!parent() || !parent()->inherits("QDeclarativeSound")) { - qWarning("PlayVariation must be defined inside Sound!"); - return; - } -} - -void QDeclarativePlayVariation::componentComplete() +void QDeclarativePlayVariation::setEngine(QDeclarativeAudioEngine *engine) { if (m_maxGain < m_minGain) { qWarning("PlayVariation: maxGain must be no less than minGain"); @@ -132,7 +126,7 @@ void QDeclarativePlayVariation::componentComplete() qWarning("PlayVariation: maxPitch must be no less than minPitch"); qSwap(m_minPitch, m_maxPitch); } - m_complete = true; + m_engine = engine; } /*! @@ -147,7 +141,7 @@ QString QDeclarativePlayVariation::sample() const void QDeclarativePlayVariation::setSample(const QString& sample) { - if (m_complete) { + if (m_engine) { qWarning("PlayVariation: cannot change properties after initialization."); return; } @@ -166,7 +160,7 @@ bool QDeclarativePlayVariation::isLooping() const void QDeclarativePlayVariation::setLooping(bool looping) { - if (m_complete) { + if (m_engine) { qWarning("PlayVariation: cannot change properties after initialization."); return; } @@ -185,7 +179,7 @@ qreal QDeclarativePlayVariation::maxGain() const void QDeclarativePlayVariation::setMaxGain(qreal maxGain) { - if (m_complete) { + if (m_engine) { qWarning("PlayVariation: cannot change properties after initialization."); return; } @@ -208,7 +202,7 @@ qreal QDeclarativePlayVariation::minGain() const void QDeclarativePlayVariation::setMinGain(qreal minGain) { - if (m_complete) { + if (m_engine) { qWarning("PlayVariation: cannot change properties after initialization."); return; } @@ -231,7 +225,7 @@ qreal QDeclarativePlayVariation::maxPitch() const void QDeclarativePlayVariation::setMaxPitch(qreal maxPitch) { - if (m_complete) { + if (m_engine) { qWarning("PlayVariation: cannot change properties after initialization."); return; } @@ -254,7 +248,7 @@ qreal QDeclarativePlayVariation::minPitch() const void QDeclarativePlayVariation::setMinPitch(qreal minPitch) { - if (m_complete) { + if (m_engine) { qWarning("PlayVariation: cannot change properties after initialization."); return; } diff --git a/src/imports/audioengine/qdeclarative_playvariation_p.h b/src/imports/audioengine/qdeclarative_playvariation_p.h index dfe690cef..d0eed0d0a 100644 --- a/src/imports/audioengine/qdeclarative_playvariation_p.h +++ b/src/imports/audioengine/qdeclarative_playvariation_p.h @@ -35,17 +35,16 @@ #define QDECLARATIVEPLAYVARIATION_P_H #include <QtQml/qqml.h> -#include <QtQml/qqmlcomponent.h> QT_BEGIN_NAMESPACE class QDeclarativeAudioSample; class QSoundInstance; +class QDeclarativeAudioEngine; -class QDeclarativePlayVariation : public QObject, public QQmlParserStatus +class QDeclarativePlayVariation : public QObject { Q_OBJECT - Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QString sample READ sample WRITE setSample) Q_PROPERTY(bool looping READ isLooping WRITE setLooping) Q_PROPERTY(qreal maxGain READ maxGain WRITE setMaxGain) @@ -57,9 +56,6 @@ public: QDeclarativePlayVariation(QObject *parent = 0); ~QDeclarativePlayVariation(); - void classBegin(); - void componentComplete(); - QString sample() const; void setSample(const QString& sample); @@ -82,9 +78,10 @@ public: void applyParameters(QSoundInstance *soundInstance); + void setEngine(QDeclarativeAudioEngine *engine); + private: Q_DISABLE_COPY(QDeclarativePlayVariation); - bool m_complete; QString m_sample; bool m_looping; qreal m_maxGain; @@ -92,6 +89,7 @@ private: qreal m_maxPitch; qreal m_minPitch; QDeclarativeAudioSample *m_sampleObject; + QDeclarativeAudioEngine *m_engine; }; QT_END_NAMESPACE diff --git a/src/imports/audioengine/qdeclarative_sound_p.cpp b/src/imports/audioengine/qdeclarative_sound_p.cpp index fcbd76f71..f19b8dbb3 100644 --- a/src/imports/audioengine/qdeclarative_sound_p.cpp +++ b/src/imports/audioengine/qdeclarative_sound_p.cpp @@ -64,8 +64,12 @@ qreal QDeclarativeSoundCone::innerAngle() const void QDeclarativeSoundCone::setInnerAngle(qreal innerAngle) { QDeclarativeSound *s = qobject_cast<QDeclarativeSound*>(parent()); - if (s && s->m_complete) + + if (s && s->m_engine) { + qWarning("SoundCone: innerAngle not changeable after initialization."); return; + } + if (innerAngle < 0 || innerAngle > 360) { qWarning() << "innerAngle should be within[0, 360] degrees"; return; @@ -88,8 +92,12 @@ qreal QDeclarativeSoundCone::outerAngle() const void QDeclarativeSoundCone::setOuterAngle(qreal outerAngle) { QDeclarativeSound *s = qobject_cast<QDeclarativeSound*>(parent()); - if (s && s->m_complete) + + if (s && s->m_engine) { + qWarning("SoundCone: outerAngle not changeable after initialization."); return; + } + if (outerAngle < 0 || outerAngle > 360) { qWarning() << "outerAngle should be within[0, 360] degrees"; return; @@ -112,8 +120,12 @@ qreal QDeclarativeSoundCone::outerGain() const void QDeclarativeSoundCone::setOuterGain(qreal outerGain) { QDeclarativeSound *s = qobject_cast<QDeclarativeSound*>(parent()); - if (s && s->m_complete) + + if (s && s->m_engine) { + qWarning("SoundCone: outerGain not changeable after initialization."); return; + } + if (outerGain < 0 || outerGain > 1) { qWarning() << "outerGain should no less than 0 and no more than 1"; return; @@ -121,11 +133,18 @@ void QDeclarativeSoundCone::setOuterGain(qreal outerGain) m_outerGain = outerGain; } -void QDeclarativeSoundCone::componentComplete() +void QDeclarativeSoundCone::setEngine(QDeclarativeAudioEngine *engine) { + if (m_engine) { + qWarning("SoundCone: engine not changeable after initialization."); + return; + } + if (m_outerAngle < m_innerAngle) { m_outerAngle = m_innerAngle; } + + m_engine = engine; } //////////////////////////////////////////////////////////// @@ -143,7 +162,9 @@ void QDeclarativeSoundCone::componentComplete() This type is part of the \b{QtAudioEngine 1.0} module. Sound can be accessed through QtAudioEngine::AudioEngine::sounds with its unique name - and must be defined inside AudioEngine. + and must be defined inside AudioEngine or be added to it using + \l{QtAudioEngine::AudioEngine::addSound()}{AudioEngine.addSound()} + if \l Sound is created dynamically. \qml import QtQuick 2.0 @@ -194,10 +215,10 @@ void QDeclarativeSoundCone::componentComplete() QDeclarativeSound::QDeclarativeSound(QObject *parent) : QObject(parent) - , m_complete(false) , m_playType(Random) , m_attenuationModelObject(0) , m_categoryObject(0) + , m_engine(0) { m_cone = new QDeclarativeSoundCone(this); } @@ -206,20 +227,6 @@ 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 enumeration QtAudioEngine::Sound::playType @@ -239,7 +246,7 @@ QDeclarativeSound::PlayType QDeclarativeSound::playType() const void QDeclarativeSound::setPlayType(PlayType playType) { - if (m_complete) { + if (m_engine) { qWarning("Sound: playType not changeable after initialization."); return; } @@ -258,7 +265,7 @@ QString QDeclarativeSound::category() const void QDeclarativeSound::setCategory(const QString& category) { - if (m_complete) { + if (m_engine) { qWarning("Sound: category not changeable after initialization."); return; } @@ -278,7 +285,7 @@ QString QDeclarativeSound::name() const void QDeclarativeSound::setName(const QString& name) { - if (m_complete) { + if (m_engine) { qWarning("Sound: category not changeable after initialization."); return; } @@ -322,13 +329,28 @@ QDeclarativePlayVariation* QDeclarativeSound::getVariation(int index) void QDeclarativeSound::setAttenuationModel(const QString &attenuationModel) { - if (m_complete) { + if (m_engine) { qWarning("Sound: attenuationModel not changeable after initialization."); return; } m_attenuationModel = attenuationModel; } +void QDeclarativeSound::setEngine(QDeclarativeAudioEngine *engine) +{ + if (m_engine) { + qWarning("Sound: engine not changeable after initialization."); + return; + } + m_cone->setEngine(engine); + m_engine = engine; +} + +QDeclarativeAudioEngine *QDeclarativeSound::engine() const +{ + return m_engine; +} + QDeclarativeSoundCone* QDeclarativeSound::cone() const { return m_cone; @@ -367,11 +389,42 @@ QList<QDeclarativePlayVariation*>& QDeclarativeSound::playlist() void QDeclarativeSound::appendFunction(QQmlListProperty<QDeclarativePlayVariation> *property, QDeclarativePlayVariation *value) { QDeclarativeSound *sound = static_cast<QDeclarativeSound*>(property->object); - if (sound->m_complete) { - qWarning("Sound: PlayVariation not addable after initialization."); + if (sound->m_engine) { return; } - sound->m_playlist.append(value); + sound->addPlayVariation(value); +} + +/*! + \qmlmethod QtAudioEngine::Sound::addPlayVariation(PlayVariation playVariation) + + Adds the given \a playVariation to sound. + This can be used when the PlayVariation is created dynamically: + + \qml + import QtAudioEngine 1.1 + + AudioEngine { + id: engine + + Component.onCompleted: { + var playVariation = Qt.createQmlObject('import QtAudioEngine 1.1; PlayVariation {}', engine); + playVariation.sample = "sample"; + playVariation.minPitch = 0.8 + playVariation.maxPitch = 1.1 + + var sound = Qt.createQmlObject('import QtAudioEngine 1.1; Sound {}', engine); + sound.name = "example"; + sound.addPlayVariation(playVariation); + engine.addSound(sound); + } + } + \endqml +*/ +void QDeclarativeSound::addPlayVariation(QDeclarativePlayVariation *value) +{ + m_playlist.append(value); + value->setEngine(m_engine); } /*! @@ -507,7 +560,7 @@ void QDeclarativeSound::play(const QVector3D& position, const QVector3D& velocit */ void QDeclarativeSound::play(const QVector3D& position, const QVector3D& velocity, const QVector3D& direction, qreal gain, qreal pitch) { - if (!m_complete) { + if (!m_engine) { qWarning() << "AudioEngine::play not ready!"; return; } @@ -546,8 +599,13 @@ QDeclarativeSoundInstance* QDeclarativeSound::newInstance() QDeclarativeSoundInstance* QDeclarativeSound::newInstance(bool managed) { + if (!m_engine) { + qWarning("engine attrbiute must be set for Sound object!"); + return NULL; + } + QDeclarativeSoundInstance *instance = - qobject_cast<QDeclarativeAudioEngine*>(this->parent())->newDeclarativeSoundInstance(managed); + m_engine->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 index 14ebd1039..83b1eb2af 100644 --- a/src/imports/audioengine/qdeclarative_sound_p.h +++ b/src/imports/audioengine/qdeclarative_sound_p.h @@ -35,7 +35,6 @@ #define QDECLARATIVESOUND_P_H #include <QtQml/qqml.h> -#include <QtQml/qqmlcomponent.h> #include <QtCore/qlist.h> #include "qdeclarative_playvariation_p.h" @@ -44,6 +43,7 @@ QT_BEGIN_NAMESPACE class QDeclarativeAudioCategory; class QDeclarativeAttenuationModel; class QDeclarativeSoundInstance; +class QDeclarativeAudioEngine; class QDeclarativeSoundCone : public QObject { @@ -65,21 +65,21 @@ public: qreal outerGain() const; void setOuterGain(qreal outerGain); - void componentComplete(); + void setEngine(QDeclarativeAudioEngine *engine); private: Q_DISABLE_COPY(QDeclarativeSoundCone) qreal m_innerAngle; qreal m_outerAngle; qreal m_outerGain; + QDeclarativeAudioEngine *m_engine; }; -class QDeclarativeSound : public QObject, public QQmlParserStatus +class QDeclarativeSound : public QObject { friend class QDeclarativeSoundCone; Q_OBJECT - Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QString name READ name WRITE setName) Q_PROPERTY(PlayType playType READ playType WRITE setPlayType) Q_PROPERTY(QString category READ category WRITE setCategory) @@ -99,9 +99,6 @@ public: QDeclarativeSound(QObject *parent = 0); ~QDeclarativeSound(); - void classBegin(); - void componentComplete(); - PlayType playType() const; void setPlayType(PlayType playType); @@ -114,6 +111,9 @@ public: QString attenuationModel() const; void setAttenuationModel(const QString &attenuationModel); + QDeclarativeAudioEngine *engine() const; + void setEngine(QDeclarativeAudioEngine *); + QDeclarativeSoundCone* cone() const; QDeclarativeAttenuationModel* attenuationModelObject() const; @@ -128,6 +128,8 @@ public: QQmlListProperty<QDeclarativePlayVariation> playVariationlist(); QList<QDeclarativePlayVariation*>& playlist(); + Q_INVOKABLE Q_REVISION(1) void addPlayVariation(QDeclarativePlayVariation*); + public Q_SLOTS: void play(); void play(qreal gain); @@ -147,7 +149,6 @@ private: Q_DISABLE_COPY(QDeclarativeSound) QDeclarativeSoundInstance* newInstance(bool managed); static void appendFunction(QQmlListProperty<QDeclarativePlayVariation> *property, QDeclarativePlayVariation *value); - bool m_complete; PlayType m_playType; QString m_name; QString m_category; @@ -157,6 +158,7 @@ private: QDeclarativeAttenuationModel *m_attenuationModelObject; QDeclarativeAudioCategory *m_categoryObject; + QDeclarativeAudioEngine *m_engine; }; QT_END_NAMESPACE |