diff options
Diffstat (limited to 'src/imports')
22 files changed, 1703 insertions, 242 deletions
diff --git a/src/imports/audioengine/audioengine.cpp b/src/imports/audioengine/audioengine.cpp index 612524447..aa2d195c5 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 + qmlRegisterType<QDeclarativeAudioEngine, 1>(uri, 1, 1, "AudioEngine"); + qmlRegisterType<QDeclarativeSound, 1>(uri, 1, 1, "Sound"); } }; diff --git a/src/imports/audioengine/plugins.qmltypes b/src/imports/audioengine/plugins.qmltypes index 8c6267bda..22fad073a 100644 --- a/src/imports/audioengine/plugins.qmltypes +++ b/src/imports/audioengine/plugins.qmltypes @@ -1,11 +1,13 @@ -import QtQuick.tooling 1.1 +import QtQuick.tooling 1.2 // This file describes the plugin-supplied types contained in the library. // It is used for QML tooling purposes only. // -// This file was auto-generated with the command 'qmlplugindump -notrelocatable QtAudioEngine 1.0'. +// This file was auto-generated by: +// 'qmlplugindump -nonrelocatable QtAudioEngine 1.0' Module { + dependencies: [] Component { name: "QDeclarativeAttenuationModel" prototype: "QObject" @@ -50,8 +52,11 @@ Module { name: "QDeclarativeAudioEngine" defaultProperty: "bank" prototype: "QObject" - exports: ["QtAudioEngine/AudioEngine 1.0"] - exportMetaObjectRevisions: [0] + exports: [ + "QtAudioEngine/AudioEngine 1.0", + "QtAudioEngine/AudioEngine 1.1" + ] + exportMetaObjectRevisions: [0, 1] Property { name: "bank"; type: "QObject"; isList: true; isReadonly: true } Property { name: "categories"; type: "QObject"; isReadonly: true; isPointer: true } Property { name: "samples"; type: "QObject"; isReadonly: true; isPointer: true } @@ -70,6 +75,26 @@ Module { Signal { name: "liveInstanceCountChanged" } Signal { name: "isLoadingChanged" } Signal { name: "finishedLoading" } + Method { + name: "addAudioSample" + revision: 1 + Parameter { type: "QDeclarativeAudioSample"; isPointer: true } + } + Method { + name: "addSound" + revision: 1 + Parameter { type: "QDeclarativeSound"; isPointer: true } + } + Method { + name: "addAudioCategory" + revision: 1 + Parameter { type: "QDeclarativeAudioCategory"; isPointer: true } + } + Method { + name: "addAttenuationModel" + revision: 1 + Parameter { type: "QDeclarativeAttenuationModel"; isPointer: true } + } } Component { name: "QDeclarativeAudioListener" @@ -111,8 +136,8 @@ Module { name: "QDeclarativeSound" defaultProperty: "playVariationlist" prototype: "QObject" - exports: ["QtAudioEngine/Sound 1.0"] - exportMetaObjectRevisions: [0] + exports: ["QtAudioEngine/Sound 1.0", "QtAudioEngine/Sound 1.1"] + exportMetaObjectRevisions: [0, 1] Enum { name: "PlayType" values: { @@ -196,6 +221,11 @@ Module { Parameter { name: "pitch"; type: "double" } } Method { name: "newInstance"; type: "QDeclarativeSoundInstance*" } + Method { + name: "addPlayVariation" + revision: 1 + Parameter { type: "QDeclarativePlayVariation"; isPointer: true } + } } Component { name: "QDeclarativeSoundCone" 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 diff --git a/src/imports/multimedia/Video.qml b/src/imports/multimedia/Video.qml index 2312924d9..1ce3065e9 100644 --- a/src/imports/multimedia/Video.qml +++ b/src/imports/multimedia/Video.qml @@ -32,7 +32,7 @@ ****************************************************************************/ import QtQuick 2.0 -import QtMultimedia 5.0 +import QtMultimedia 5.6 /*! \qmltype Video @@ -274,6 +274,35 @@ Item { property alias position: player.position /*! + \qmlproperty enumeration Video::audioRole + + This property holds the role of the audio stream. It can be set to specify the type of audio + being played, allowing the system to make appropriate decisions when it comes to volume, + routing or post-processing. + + The audio role must be set before setting the source property. + + Supported values can be retrieved with supportedAudioRoles(). + + The value can be one of: + \list + \li MediaPlayer.UnknownRole - the role is unknown or undefined. + \li MediaPlayer.MusicRole - music. + \li MediaPlayer.VideoRole - soundtrack from a movie or a video. + \li MediaPlayer.VoiceCommunicationRole - voice communications, such as telephony. + \li MediaPlayer.AlarmRole - alarm. + \li MediaPlayer.NotificationRole - notification, such as an incoming e-mail or a chat request. + \li MediaPlayer.RingtoneRole - ringtone. + \li MediaPlayer.AccessibilityRole - for accessibility, such as with a screen reader. + \li MediaPlayer.SonificationRole - sonification, such as with user interface sounds. + \li MediaPlayer.GameRole - game audio. + \endlist + + \since 5.6 + */ + property alias audioRole: player.audioRole + + /*! \qmlproperty bool Video::seekable This property holds whether the playback position of the video can be @@ -287,10 +316,23 @@ Item { \qmlproperty url Video::source This property holds the source URL of the media. + + Setting the \l source property clears the current \l playlist, if any. */ property alias source: player.source /*! + \qmlproperty Playlist Video::playlist + + This property holds the playlist used by the media player. + + Setting the \l playlist property resets the \l source to an empty string. + + \since 5.6 + */ + property alias playlist: player.playlist + + /*! \qmlproperty enumeration Video::status This property holds the status of media loading. It can be one of: @@ -407,4 +449,18 @@ Item { player.seek(offset); } + /*! + \qmlmethod list<int> Video::supportedAudioRoles() + + Returns a list of supported audio roles. + + If setting the audio role is not supported, an empty list is returned. + + \since 5.6 + \sa audioRole + */ + function supportedAudioRoles() { + return player.supportedAudioRoles(); + } + } diff --git a/src/imports/multimedia/multimedia.cpp b/src/imports/multimedia/multimedia.cpp index 4b31068ea..7d34672a1 100644 --- a/src/imports/multimedia/multimedia.cpp +++ b/src/imports/multimedia/multimedia.cpp @@ -45,6 +45,7 @@ #include "qdeclarativeaudio_p.h" #include "qdeclarativeradio_p.h" #include "qdeclarativeradiodata_p.h" +#include "qdeclarativeplaylist_p.h" #include "qdeclarativecamera_p.h" #include "qdeclarativecamerapreviewprovider_p.h" #include "qdeclarativecameraexposure_p.h" @@ -114,6 +115,12 @@ public: qmlRegisterUncreatableType<QDeclarativeCameraImageProcessing, 1>(uri, 5, 5, "CameraImageProcessing", trUtf8("CameraImageProcessing is provided by Camera")); qmlRegisterType<QDeclarativeCamera, 2>(uri, 5, 5, "Camera"); + // 5.6 types + qmlRegisterType<QDeclarativeAudio, 1>(uri, 5, 6, "Audio"); + qmlRegisterType<QDeclarativeAudio, 1>(uri, 5, 6, "MediaPlayer"); + qmlRegisterType<QDeclarativePlaylist>(uri, 5, 6, "Playlist"); + qmlRegisterType<QDeclarativePlaylistItem>(uri, 5, 6, "PlaylistItem"); + qmlRegisterType<QDeclarativeMediaMetaData>(); qmlRegisterType<QAbstractVideoFilter>(); } diff --git a/src/imports/multimedia/multimedia.pro b/src/imports/multimedia/multimedia.pro index 71358caed..606fb3966 100644 --- a/src/imports/multimedia/multimedia.pro +++ b/src/imports/multimedia/multimedia.pro @@ -3,6 +3,7 @@ QT += qml quick network multimedia-private qtmultimediaquicktools-private HEADERS += \ qdeclarativeaudio_p.h \ qdeclarativemediametadata_p.h \ + qdeclarativeplaylist_p.h \ qdeclarativeradio_p.h \ qdeclarativeradiodata_p.h \ qdeclarativecamera_p.h \ @@ -20,6 +21,7 @@ HEADERS += \ SOURCES += \ multimedia.cpp \ qdeclarativeaudio.cpp \ + qdeclarativeplaylist.cpp \ qdeclarativeradio.cpp \ qdeclarativeradiodata.cpp \ qdeclarativecamera.cpp \ diff --git a/src/imports/multimedia/plugins.qmltypes b/src/imports/multimedia/plugins.qmltypes index 53d7cb435..fe1c68af2 100644 --- a/src/imports/multimedia/plugins.qmltypes +++ b/src/imports/multimedia/plugins.qmltypes @@ -4,7 +4,7 @@ import QtQuick.tooling 1.2 // It is used for QML tooling purposes only. // // This file was auto-generated by: -// 'qmlplugindump -nonrelocatable QtMultimedia 5.5' +// 'qmlplugindump -nonrelocatable QtMultimedia 5.6' Module { dependencies: ["QtQuick 2.0"] @@ -146,8 +146,13 @@ Module { Component { name: "QDeclarativeAudio" prototype: "QObject" - exports: ["QtMultimedia/Audio 5.0", "QtMultimedia/MediaPlayer 5.0"] - exportMetaObjectRevisions: [0, 0] + exports: [ + "QtMultimedia/Audio 5.0", + "QtMultimedia/Audio 5.6", + "QtMultimedia/MediaPlayer 5.0", + "QtMultimedia/MediaPlayer 5.6" + ] + exportMetaObjectRevisions: [0, 1, 0, 1] Enum { name: "Status" values: { @@ -196,7 +201,23 @@ Module { "ResourceMissing": 3 } } + Enum { + name: "AudioRole" + values: { + "UnknownRole": 0, + "AccessibilityRole": 7, + "AlarmRole": 4, + "GameRole": 9, + "MusicRole": 1, + "NotificationRole": 5, + "RingtoneRole": 6, + "SonificationRole": 8, + "VideoRole": 2, + "VoiceCommunicationRole": 3 + } + } Property { name: "source"; type: "QUrl" } + Property { name: "playlist"; revision: 1; type: "QDeclarativePlaylist"; isPointer: true } Property { name: "loops"; type: "int" } Property { name: "playbackState"; type: "PlaybackState"; isReadonly: true } Property { name: "autoPlay"; type: "bool" } @@ -221,10 +242,13 @@ Module { } Property { name: "mediaObject"; type: "QObject"; isReadonly: true; isPointer: true } Property { name: "availability"; type: "Availability"; isReadonly: true } + Property { name: "audioRole"; revision: 1; type: "AudioRole" } + Signal { name: "playlistChanged"; revision: 1 } Signal { name: "loopCountChanged" } Signal { name: "paused" } Signal { name: "stopped" } Signal { name: "playing" } + Signal { name: "audioRoleChanged"; revision: 1 } Signal { name: "availabilityChanged" Parameter { name: "availability"; type: "Availability" } @@ -241,6 +265,7 @@ Module { name: "seek" Parameter { name: "position"; type: "int" } } + Method { name: "supportedAudioRoles"; revision: 1; type: "QJSValue" } } Component { name: "QDeclarativeCamera" @@ -1215,6 +1240,137 @@ Module { Property { name: "availableCameras"; type: "QJSValue"; isReadonly: true } } Component { + name: "QDeclarativePlaylist" + defaultProperty: "items" + prototype: "QAbstractListModel" + exports: ["QtMultimedia/Playlist 5.6"] + exportMetaObjectRevisions: [0] + Enum { + name: "PlaybackMode" + values: { + "CurrentItemOnce": 0, + "CurrentItemInLoop": 1, + "Sequential": 2, + "Loop": 3, + "Random": 4 + } + } + Enum { + name: "Error" + values: { + "NoError": 0, + "FormatError": 1, + "FormatNotSupportedError": 2, + "NetworkError": 3, + "AccessDeniedError": 4 + } + } + Property { name: "playbackMode"; type: "PlaybackMode" } + Property { name: "currentItemSource"; type: "QUrl"; isReadonly: true } + Property { name: "currentIndex"; type: "int" } + Property { name: "itemCount"; type: "int"; isReadonly: true } + Property { name: "readOnly"; type: "bool"; isReadonly: true } + Property { name: "error"; type: "Error"; isReadonly: true } + Property { name: "errorString"; type: "string"; isReadonly: true } + Property { name: "items"; type: "QDeclarativePlaylistItem"; isList: true; isReadonly: true } + Signal { + name: "itemAboutToBeInserted" + Parameter { name: "start"; type: "int" } + Parameter { name: "end"; type: "int" } + } + Signal { + name: "itemInserted" + Parameter { name: "start"; type: "int" } + Parameter { name: "end"; type: "int" } + } + Signal { + name: "itemAboutToBeRemoved" + Parameter { name: "start"; type: "int" } + Parameter { name: "end"; type: "int" } + } + Signal { + name: "itemRemoved" + Parameter { name: "start"; type: "int" } + Parameter { name: "end"; type: "int" } + } + Signal { + name: "itemChanged" + Parameter { name: "start"; type: "int" } + Parameter { name: "end"; type: "int" } + } + Signal { name: "loaded" } + Signal { name: "loadFailed" } + Signal { + name: "error" + Parameter { name: "error"; type: "QDeclarativePlaylist::Error" } + Parameter { name: "errorString"; type: "string" } + } + Method { + name: "itemSource" + type: "QUrl" + Parameter { name: "index"; type: "int" } + } + Method { + name: "nextIndex" + type: "int" + Parameter { name: "steps"; type: "int" } + } + Method { name: "nextIndex"; type: "int" } + Method { + name: "previousIndex" + type: "int" + Parameter { name: "steps"; type: "int" } + } + Method { name: "previousIndex"; type: "int" } + Method { name: "next" } + Method { name: "previous" } + Method { name: "shuffle" } + Method { + name: "load" + Parameter { name: "location"; type: "QUrl" } + Parameter { name: "format"; type: "string" } + } + Method { + name: "load" + Parameter { name: "location"; type: "QUrl" } + } + Method { + name: "save" + type: "bool" + Parameter { name: "location"; type: "QUrl" } + Parameter { name: "format"; type: "string" } + } + Method { + name: "save" + type: "bool" + Parameter { name: "location"; type: "QUrl" } + } + Method { + name: "addItem" + type: "bool" + Parameter { name: "source"; type: "QUrl" } + } + Method { + name: "insertItem" + type: "bool" + Parameter { name: "index"; type: "int" } + Parameter { name: "source"; type: "QUrl" } + } + Method { + name: "removeItem" + type: "bool" + Parameter { name: "index"; type: "int" } + } + Method { name: "clear"; type: "bool" } + } + Component { + name: "QDeclarativePlaylistItem" + prototype: "QObject" + exports: ["QtMultimedia/PlaylistItem 5.6"] + exportMetaObjectRevisions: [0] + Property { name: "source"; type: "QUrl" } + } + Component { name: "QDeclarativeRadio" prototype: "QObject" exports: ["QtMultimedia/Radio 5.0"] diff --git a/src/imports/multimedia/qdeclarativeaudio.cpp b/src/imports/multimedia/qdeclarativeaudio.cpp index 540ed6464..7decc4f19 100644 --- a/src/imports/multimedia/qdeclarativeaudio.cpp +++ b/src/imports/multimedia/qdeclarativeaudio.cpp @@ -42,9 +42,11 @@ #include <qmetadatareadercontrol.h> #include <qmediaavailabilitycontrol.h> +#include "qdeclarativeplaylist_p.h" #include "qdeclarativemediametadata_p.h" #include <QTimerEvent> +#include <QtQml/qqmlengine.h> QT_BEGIN_NAMESPACE @@ -94,16 +96,19 @@ void QDeclarativeAudio::_q_availabilityChanged(QMultimedia::AvailabilityStatus) QDeclarativeAudio::QDeclarativeAudio(QObject *parent) : QObject(parent) + , m_playlist(0) , m_autoPlay(false) , m_autoLoad(true) , m_loaded(false) , m_muted(false) , m_complete(false) + , m_emitPlaylistChanged(false) , m_loopCount(1) , m_runningCount(0) , m_position(0) , m_vol(1.0) , m_playbackRate(1.0) + , m_audioRole(UnknownRole) , m_playbackState(QMediaPlayer::StoppedState) , m_status(QMediaPlayer::NoMedia) , m_error(QMediaPlayer::ServiceMissingError) @@ -144,11 +149,122 @@ QDeclarativeAudio::Availability QDeclarativeAudio::availability() const return Availability(m_player->availability()); } +/*! + \qmlproperty enumeration QtMultimedia::Audio::audioRole + + This property holds the role of the audio stream. It can be set to specify the type of audio + being played, allowing the system to make appropriate decisions when it comes to volume, + routing or post-processing. + + The audio role must be set before setting the source property. + + Supported values can be retrieved with supportedAudioRoles(). + + The value can be one of: + \list + \li UnknownRole - the role is unknown or undefined. + \li MusicRole - music. + \li VideoRole - soundtrack from a movie or a video. + \li VoiceCommunicationRole - voice communications, such as telephony. + \li AlarmRole - alarm. + \li NotificationRole - notification, such as an incoming e-mail or a chat request. + \li RingtoneRole - ringtone. + \li AccessibilityRole - for accessibility, such as with a screen reader. + \li SonificationRole - sonification, such as with user interface sounds. + \li GameRole - game audio. + \endlist + + \since 5.6 +*/ +QDeclarativeAudio::AudioRole QDeclarativeAudio::audioRole() const +{ + return !m_complete ? m_audioRole : AudioRole(m_player->audioRole()); +} + +void QDeclarativeAudio::setAudioRole(QDeclarativeAudio::AudioRole audioRole) +{ + if (this->audioRole() == audioRole) + return; + + if (m_complete) { + m_player->setAudioRole(QAudio::Role(audioRole)); + } else { + m_audioRole = audioRole; + emit audioRoleChanged(); + } +} + +/*! + \qmlmethod list<int> QtMultimedia::Audio::supportedAudioRoles() + + Returns a list of supported audio roles. + + If setting the audio role is not supported, an empty list is returned. + + \since 5.6 + \sa audioRole +*/ +QJSValue QDeclarativeAudio::supportedAudioRoles() const +{ + QJSEngine *engine = qmlEngine(this); + + if (!m_complete) + return engine->newArray(); + + QList<QAudio::Role> roles = m_player->supportedAudioRoles(); + int size = roles.size(); + + QJSValue result = engine->newArray(size); + for (int i = 0; i < size; ++i) + result.setProperty(i, roles.at(i)); + + return result; +} + QUrl QDeclarativeAudio::source() const { return m_source; } +QDeclarativePlaylist *QDeclarativeAudio::playlist() const +{ + return m_playlist; +} + +void QDeclarativeAudio::setPlaylist(QDeclarativePlaylist *playlist) +{ + if (playlist == m_playlist && m_source.isEmpty()) + return; + + if (!m_source.isEmpty()) { + m_source.clear(); + emit sourceChanged(); + } + + m_playlist = playlist; + m_content = m_playlist ? + QMediaContent(m_playlist->mediaPlaylist(), QUrl(), false) : QMediaContent(); + m_loaded = false; + if (m_complete && (m_autoLoad || m_content.isNull() || m_autoPlay)) { + if (m_error != QMediaPlayer::ServiceMissingError && m_error != QMediaPlayer::NoError) { + m_error = QMediaPlayer::NoError; + m_errorString = QString(); + + emit errorChanged(); + } + + if (!playlist) + m_emitPlaylistChanged = true; + m_player->setMedia(m_content, 0); + m_loaded = true; + } + else + emit playlistChanged(); + + if (m_autoPlay) + m_player->play(); +} + bool QDeclarativeAudio::autoPlay() const { return m_autoPlay; @@ -166,9 +282,14 @@ void QDeclarativeAudio::setAutoPlay(bool autoplay) void QDeclarativeAudio::setSource(const QUrl &url) { - if (url == m_source) + if (url == m_source && m_playlist == NULL) return; + if (m_playlist) { + m_playlist = NULL; + emit playlistChanged(); + } + m_source = url; m_content = m_source.isEmpty() ? QMediaContent() : m_source; m_loaded = false; @@ -425,6 +546,18 @@ void QDeclarativeAudio::seek(int position) \qmlproperty url QtMultimedia::Audio::source This property holds the source URL of the media. + + Setting the \l source property clears the current \l playlist, if any. +*/ + +/*! + \qmlproperty Playlist QtMultimedia::Audio::playlist + + This property holds the playlist used by the media player. + + Setting the \l playlist property resets the \l source to an empty string. + + \since 5.6 */ /*! @@ -650,8 +783,8 @@ void QDeclarativeAudio::classBegin() this, SLOT(_q_statusChanged())); connect(m_player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(_q_statusChanged())); - connect(m_player, SIGNAL(mediaChanged(QMediaContent)), - this, SIGNAL(sourceChanged())); + connect(m_player, SIGNAL(mediaChanged(const QMediaContent&)), + this, SLOT(_q_mediaChanged(const QMediaContent&))); connect(m_player, SIGNAL(durationChanged(qint64)), this, SIGNAL(durationChanged())); connect(m_player, SIGNAL(positionChanged(qint64)), @@ -672,6 +805,8 @@ void QDeclarativeAudio::classBegin() this, SIGNAL(hasAudioChanged())); connect(m_player, SIGNAL(videoAvailableChanged(bool)), this, SIGNAL(hasVideoChanged())); + connect(m_player, SIGNAL(audioRoleChanged(QAudio::Role)), + this, SIGNAL(audioRoleChanged())); m_error = m_player->availability() == QMultimedia::ServiceMissing ? QMediaPlayer::ServiceMissingError : QMediaPlayer::NoError; @@ -694,6 +829,8 @@ void QDeclarativeAudio::componentComplete() m_player->setMuted(m_muted); if (!qFuzzyCompare(m_playbackRate, qreal(1.0))) m_player->setPlaybackRate(m_playbackRate); + if (m_audioRole != UnknownRole) + m_player->setAudioRole(QAudio::Role(m_audioRole)); if (!m_content.isNull() && (m_autoLoad || m_autoPlay)) { m_player->setMedia(m_content, 0); @@ -752,6 +889,16 @@ void QDeclarativeAudio::_q_statusChanged() } } +void QDeclarativeAudio::_q_mediaChanged(const QMediaContent &media) +{ + if (!media.playlist() && !m_emitPlaylistChanged) { + emit sourceChanged(); + } else { + m_emitPlaylistChanged = false; + emit playlistChanged(); + } +} + /*! \qmlproperty string QtMultimedia::Audio::errorString @@ -965,6 +1112,45 @@ void QDeclarativeAudio::_q_statusChanged() */ /*! + \qmlproperty enumeration QtMultimedia::MediaPlayer::audioRole + + This property holds the role of the audio stream. It can be set to specify the type of audio + being played, allowing the system to make appropriate decisions when it comes to volume, + routing or post-processing. + + The audio role must be set before setting the source property. + + Supported values can be retrieved with supportedAudioRoles(). + + The value can be one of: + \list + \li UnknownRole - the role is unknown or undefined. + \li MusicRole - music. + \li VideoRole - soundtrack from a movie or a video. + \li VoiceCommunicationRole - voice communications, such as telephony. + \li AlarmRole - alarm. + \li NotificationRole - notification, such as an incoming e-mail or a chat request. + \li RingtoneRole - ringtone. + \li AccessibilityRole - for accessibility, such as with a screen reader. + \li SonificationRole - sonification, such as with user interface sounds. + \li GameRole - game audio. + \endlist + + \since 5.6 +*/ + +/*! + \qmlmethod list<int> QtMultimedia::MediaPlayer::supportedAudioRoles() + + Returns a list of supported audio roles. + + If setting the audio role is not supported, an empty list is returned. + + \since 5.6 + \sa audioRole +*/ + +/*! \qmlmethod QtMultimedia::MediaPlayer::play() Starts playback of the media. @@ -992,6 +1178,18 @@ void QDeclarativeAudio::_q_statusChanged() \qmlproperty url QtMultimedia::MediaPlayer::source This property holds the source URL of the media. + + Setting the \l source property clears the current \l playlist, if any. +*/ + +/*! + \qmlproperty Playlist QtMultimedia::MediaPlayer::playlist + + This property holds the playlist used by the media player. + + Setting the \l playlist property resets the \l source to an empty string. + + \since 5.6 */ /*! diff --git a/src/imports/multimedia/qdeclarativeaudio_p.h b/src/imports/multimedia/qdeclarativeaudio_p.h index d4840f207..d8363969d 100644 --- a/src/imports/multimedia/qdeclarativeaudio_p.h +++ b/src/imports/multimedia/qdeclarativeaudio_p.h @@ -48,6 +48,7 @@ #include <QtCore/qbasictimer.h> #include <QtQml/qqmlparserstatus.h> #include <QtQml/qqml.h> +#include <QtQml/qjsvalue.h> #include <qmediaplayer.h> @@ -58,6 +59,7 @@ class QMediaPlayerControl; class QMediaService; class QMediaServiceProvider; class QMetaDataReaderControl; +class QDeclarativePlaylist; class QDeclarativeMediaBaseAnimation; class QDeclarativeMediaMetaData; class QMediaAvailabilityControl; @@ -66,6 +68,7 @@ class QDeclarativeAudio : public QObject, public QQmlParserStatus { Q_OBJECT Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) + Q_PROPERTY(QDeclarativePlaylist *playlist READ playlist WRITE setPlaylist NOTIFY playlistChanged REVISION 1) Q_PROPERTY(int loops READ loopCount WRITE setLoopCount NOTIFY loopCountChanged) Q_PROPERTY(PlaybackState playbackState READ playbackState NOTIFY playbackStateChanged) Q_PROPERTY(bool autoPlay READ autoPlay WRITE setAutoPlay NOTIFY autoPlayChanged) @@ -85,11 +88,13 @@ class QDeclarativeAudio : public QObject, public QQmlParserStatus Q_PROPERTY(QDeclarativeMediaMetaData *metaData READ metaData CONSTANT) Q_PROPERTY(QObject *mediaObject READ mediaObject NOTIFY mediaObjectChanged SCRIPTABLE false DESIGNABLE false) Q_PROPERTY(Availability availability READ availability NOTIFY availabilityChanged) + Q_PROPERTY(AudioRole audioRole READ audioRole WRITE setAudioRole NOTIFY audioRoleChanged REVISION 1) Q_ENUMS(Status) Q_ENUMS(Error) Q_ENUMS(Loop) Q_ENUMS(PlaybackState) Q_ENUMS(Availability) + Q_ENUMS(AudioRole) Q_INTERFACES(QQmlParserStatus) public: enum Status @@ -134,6 +139,19 @@ public: ResourceMissing = QMultimedia::ResourceError }; + enum AudioRole { + UnknownRole = QAudio::UnknownRole, + AccessibilityRole = QAudio::AccessibilityRole, + AlarmRole = QAudio::AlarmRole, + GameRole = QAudio::GameRole, + MusicRole = QAudio::MusicRole, + NotificationRole = QAudio::NotificationRole, + RingtoneRole = QAudio::RingtoneRole, + SonificationRole = QAudio::SonificationRole, + VideoRole = QAudio::VideoRole, + VoiceCommunicationRole = QAudio::VoiceCommunicationRole + }; + QDeclarativeAudio(QObject *parent = 0); ~QDeclarativeAudio(); @@ -152,9 +170,15 @@ public: Availability availability() const; + AudioRole audioRole() const; + void setAudioRole(AudioRole audioRole); + QUrl source() const; void setSource(const QUrl &url); + QDeclarativePlaylist *playlist() const; + void setPlaylist(QDeclarativePlaylist *playlist); + int loopCount() const; void setLoopCount(int loopCount); @@ -191,7 +215,11 @@ public Q_SLOTS: void stop(); void seek(int position); + Q_REVISION(1) QJSValue supportedAudioRoles() const; + Q_SIGNALS: + Q_REVISION(1) void playlistChanged(); + void sourceChanged(); void autoLoadChanged(); void loopCountChanged(); @@ -218,6 +246,8 @@ Q_SIGNALS: void seekableChanged(); void playbackRateChanged(); + Q_REVISION(1) void audioRoleChanged(); + void availabilityChanged(Availability availability); void errorChanged(); @@ -229,20 +259,24 @@ private Q_SLOTS: void _q_error(QMediaPlayer::Error); void _q_availabilityChanged(QMultimedia::AvailabilityStatus); void _q_statusChanged(); + void _q_mediaChanged(const QMediaContent&); private: Q_DISABLE_COPY(QDeclarativeAudio) + QDeclarativePlaylist *m_playlist; bool m_autoPlay; bool m_autoLoad; bool m_loaded; bool m_muted; bool m_complete; + bool m_emitPlaylistChanged; int m_loopCount; int m_runningCount; int m_position; qreal m_vol; qreal m_playbackRate; + AudioRole m_audioRole; QMediaPlayer::State m_playbackState; QMediaPlayer::MediaStatus m_status; diff --git a/src/imports/multimedia/qdeclarativeplaylist.cpp b/src/imports/multimedia/qdeclarativeplaylist.cpp new file mode 100644 index 000000000..bb785aa98 --- /dev/null +++ b/src/imports/multimedia/qdeclarativeplaylist.cpp @@ -0,0 +1,583 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativeplaylist_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \qmltype PlaylistItem + \instantiates QDeclarativePlaylistItem + \since 5.6 + + \inqmlmodule QtMultimedia + \ingroup multimedia_qml + \ingroup multimedia_audio_qml + \ingroup multimedia_video_qml + \brief Defines an item in a Playlist. + + \sa Playlist +*/ + +/*! + \qmlproperty url QtMultimedia::PlaylistItem::source + + This property holds the source URL of the item. + + \sa Playlist +*/ +QDeclarativePlaylistItem::QDeclarativePlaylistItem(QObject *parent) + : QObject(parent) +{ +} + +QUrl QDeclarativePlaylistItem::source() const +{ + return m_source; +} + +void QDeclarativePlaylistItem::setSource(const QUrl &source) +{ + m_source = source; +} + +/*! + \qmltype Playlist + \instantiates QDeclarativePlaylist + \since 5.6 + \brief For specifying a list of media to be played. + + \inqmlmodule QtMultimedia + \ingroup multimedia_qml + \ingroup multimedia_audio_qml + \ingroup multimedia_video_qml + + The Playlist type provides a way to play a list of media with the MediaPlayer, Audio and Video + types. It can be used as a data source for view elements (such as ListView) and other elements + that interact with model data (such as Repeater). When used as a data model, each playlist + item's source URL can be accessed using the \c source role. + + \qml + import QtQuick 2.0 + import QtMultimedia 5.6 + + Item { + width: 400; + height: 300; + + Audio { + id: player; + playlist: Playlist { + id: playlist + PlaylistItem { source: "song1.ogg"; } + PlaylistItem { source: "song2.ogg"; } + PlaylistItem { source: "song3.ogg"; } + } + } + + ListView { + model: playlist; + delegate: Text { + font.pixelSize: 16; + text: source; + } + } + + MouseArea { + anchors.fill: parent; + onPressed: { + if (player.playbackState != Audio.PlayingState) { + player.play(); + } else { + player.pause(); + } + } + } + } + \endqml + + \sa MediaPlayer, Audio, Video +*/ + +void QDeclarativePlaylist::_q_mediaAboutToBeInserted(int start, int end) +{ + emit itemAboutToBeInserted(start, end); + + beginInsertRows(QModelIndex(), start, end); +} + +void QDeclarativePlaylist::_q_mediaInserted(int start, int end) +{ + endInsertRows(); + + emit itemCountChanged(); + emit itemInserted(start, end); +} + +void QDeclarativePlaylist::_q_mediaAboutToBeRemoved(int start, int end) +{ + emit itemAboutToBeRemoved(start, end); + + beginRemoveRows(QModelIndex(), start, end); +} + +void QDeclarativePlaylist::_q_mediaRemoved(int start, int end) +{ + endRemoveRows(); + + emit itemCountChanged(); + emit itemRemoved(start, end); +} + +void QDeclarativePlaylist::_q_mediaChanged(int start, int end) +{ + emit dataChanged(createIndex(start, 0), createIndex(end, 0)); + emit itemChanged(start, end); +} + +void QDeclarativePlaylist::_q_loadFailed() +{ + m_error = m_playlist->error(); + m_errorString = m_playlist->errorString(); + + emit error(Error(m_error), m_errorString); + emit errorChanged(); + emit loadFailed(); +} + +QDeclarativePlaylist::QDeclarativePlaylist(QObject *parent) + : QAbstractListModel(parent) + , m_playlist(0) + , m_error(QMediaPlaylist::NoError) + , m_readOnly(false) +{ +} + +QDeclarativePlaylist::~QDeclarativePlaylist() +{ + delete m_playlist; +} + +/*! + \qmlproperty enumeration QtMultimedia::Playlist::playbackMode + + This property holds the order in which items in the playlist are played. + + \table + \header \li Value \li Description + \row \li CurrentItemOnce + \li The current item is played only once. + \row \li CurrentItemInLoop + \li The current item is played repeatedly in a loop. + \row \li Sequential + \li Playback starts from the current and moves through each successive item until the last + is reached and then stops. The next item is a null item when the last one is currently + playing. + \row \li Loop + \li Playback restarts at the first item after the last has finished playing. + \row \li Random + \li Play items in random order. + \endtable + */ +QDeclarativePlaylist::PlaybackMode QDeclarativePlaylist::playbackMode() const +{ + return PlaybackMode(m_playlist->playbackMode()); +} + +void QDeclarativePlaylist::setPlaybackMode(PlaybackMode mode) +{ + if (playbackMode() == mode) + return; + + m_playlist->setPlaybackMode(QMediaPlaylist::PlaybackMode(mode)); +} + +/*! + \qmlproperty url QtMultimedia::Playlist::currentItemsource + + This property holds the source URL of the current item in the playlist. + */ +QUrl QDeclarativePlaylist::currentItemSource() const +{ + return m_playlist->currentMedia().canonicalUrl(); +} + +/*! + \qmlproperty int QtMultimedia::Playlist::currentIndex + + This property holds the position of the current item in the playlist. + */ +int QDeclarativePlaylist::currentIndex() const +{ + return m_playlist->currentIndex(); +} + +void QDeclarativePlaylist::setCurrentIndex(int index) +{ + if (currentIndex() == index) + return; + + m_playlist->setCurrentIndex(index); +} + +/*! + \qmlproperty int QtMultimedia::Playlist::itemCount + + This property holds the number of items in the playlist. + */ +int QDeclarativePlaylist::itemCount() const +{ + return m_playlist->mediaCount(); +} + +/*! + \qmlproperty bool QtMultimedia::Playlist::readOnly + + This property indicates if the playlist can be modified. + */ +bool QDeclarativePlaylist::readOnly() const +{ + // There's no signal to tell whether or not the read only state changed, so we consider it fixed + // after its initial retrieval in componentComplete(). + return m_readOnly; +} + +/*! + \qmlproperty enumeration QtMultimedia::Playlist::error + + This property holds the error condition of the playlist. + + \table + \header \li Value \li Description + \row \li NoError + \li No errors + \row \li FormatError + \li Format error. + \row \li FormatNotSupportedError + \li Format not supported. + \row \li NetworkError + \li Network error. + \row \li AccessDeniedError + \li Access denied error. + \endtable + */ +QDeclarativePlaylist::Error QDeclarativePlaylist::error() const +{ + return Error(m_error); +} + +/*! + \qmlproperty string QtMultimedia::Playlist::errorString + + This property holds a string describing the current error condition of the playlist. +*/ +QString QDeclarativePlaylist::errorString() const +{ + return m_errorString; +} + +/*! + \qmlmethod url QtMultimedia::Playlist::itemSource(index) + + Returns the source URL of the item at the given \a index in the playlist. +*/ +QUrl QDeclarativePlaylist::itemSource(int index) +{ + return m_playlist->media(index).canonicalUrl(); +} + +/*! + \qmlmethod int QtMultimedia::Playlist::nextIndex(steps) + + Returns the index of the item in the playlist which would be current after calling next() + \a steps times. + + Returned value depends on the size of the playlist, the current position and the playback mode. + + \sa playbackMode, previousIndex() +*/ +int QDeclarativePlaylist::nextIndex(int steps) +{ + return m_playlist->nextIndex(steps); +} + +/*! + \qmlmethod int QtMultimedia::Playlist::previousIndex(steps) + + Returns the index of the item in the playlist which would be current after calling previous() + \a steps times. + + Returned value depends on the size of the playlist, the current position and the playback mode. + + \sa playbackMode, nextIndex() +*/ +int QDeclarativePlaylist::previousIndex(int steps) +{ + return m_playlist->previousIndex(steps); +} + +/*! + \qmlmethod QtMultimedia::Playlist::next() + + Advances to the next item in the playlist. +*/ +void QDeclarativePlaylist::next() +{ + m_playlist->next(); +} + +/*! + \qmlmethod QtMultimedia::Playlist::previous() + + Returns to the previous item in the playlist. +*/ +void QDeclarativePlaylist::previous() +{ + m_playlist->previous(); +} + +/*! + \qmlmethod QtMultimedia::Playlist::shuffle() + + Shuffles items in the playlist. +*/ +void QDeclarativePlaylist::shuffle() +{ + m_playlist->shuffle(); +} + +/*! + \qmlmethod QtMultimedia::Playlist::load(location, format) + + Loads a playlist from the given \a location. If \a format is specified, it is used, otherwise + the format is guessed from the location name and the data. + + New items are appended to the playlist. + + \c onloaded() is emitted if the playlist loads successfully, otherwise \c onLoadFailed() is + emitted with \l error and \l errorString defined accordingly. +*/ +void QDeclarativePlaylist::load(const QUrl &location, const QString &format) +{ + m_error = QMediaPlaylist::NoError; + m_errorString = QString(); + emit errorChanged(); + m_playlist->load(location, format.toLatin1().constData()); +} + +/*! + \qmlmethod bool QtMultimedia::Playlist::save(location, format) + + Saves the playlist to the given \a location. If \a format is specified, it is used, otherwise + the format is guessed from the location name. + + Returns true if the playlist is saved successfully. +*/ +bool QDeclarativePlaylist::save(const QUrl &location, const QString &format) +{ + return m_playlist->save(location, format.toLatin1().constData()); +} + +/*! + \qmlmethod bool QtMultimedia::Playlist::addItem(source) + + Appends the \a source URL to the playlist. + + Returns true if the \a source is added successfully. +*/ +bool QDeclarativePlaylist::addItem(const QUrl &source) +{ + return m_playlist->addMedia(QMediaContent(source)); +} + +/*! + \qmlmethod bool QtMultimedia::Playlist::insertItem(index, source) + + Inserts the \a source URL to the playlist at the given \a index. + + Returns true if the \a source is added successfully. +*/ +bool QDeclarativePlaylist::insertItem(int index, const QUrl &source) +{ + return m_playlist->insertMedia(index, QMediaContent(source)); +} + +/*! + \qmlmethod bool QtMultimedia::Playlist::removeItem(index) + + Removed the item at the given \a index from the playlist. + + Returns true if the \a source is removed successfully. +*/ +bool QDeclarativePlaylist::removeItem(int index) +{ + return m_playlist->removeMedia(index); +} + +/*! + \qmlmethod bool QtMultimedia::Playlist::clear() + + Removes all the items from the playlist. + + Returns true if the operation is successful. +*/ +bool QDeclarativePlaylist::clear() +{ + return m_playlist->clear(); +} + +int QDeclarativePlaylist::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; + + return m_playlist->mediaCount(); +} + +QVariant QDeclarativePlaylist::data(const QModelIndex &index, int role) const +{ + Q_UNUSED(role); + + if (!index.isValid()) + return QVariant(); + + return m_playlist->media(index.row()).canonicalUrl(); +} + +QHash<int, QByteArray> QDeclarativePlaylist::roleNames() const +{ + QHash<int, QByteArray> roleNames; + roleNames[SourceRole] = "source"; + return roleNames; +} + +void QDeclarativePlaylist::classBegin() +{ + m_playlist = new QMediaPlaylist(this); + + connect(m_playlist, SIGNAL(currentIndexChanged(int)), + this, SIGNAL(currentIndexChanged())); + connect(m_playlist, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)), + this, SIGNAL(playbackModeChanged())); + connect(m_playlist, SIGNAL(currentMediaChanged(QMediaContent)), + this, SIGNAL(currentItemSourceChanged())); + connect(m_playlist, SIGNAL(mediaAboutToBeInserted(int,int)), + this, SLOT(_q_mediaAboutToBeInserted(int,int))); + connect(m_playlist, SIGNAL(mediaInserted(int,int)), + this, SLOT(_q_mediaInserted(int,int))); + connect(m_playlist, SIGNAL(mediaAboutToBeRemoved(int,int)), + this, SLOT(_q_mediaAboutToBeRemoved(int,int))); + connect(m_playlist, SIGNAL(mediaRemoved(int,int)), + this, SLOT(_q_mediaRemoved(int,int))); + connect(m_playlist, SIGNAL(mediaChanged(int,int)), + this, SLOT(_q_mediaChanged(int,int))); + connect(m_playlist, SIGNAL(loaded()), + this, SIGNAL(loaded())); + connect(m_playlist, SIGNAL(loadFailed()), + this, SLOT(_q_loadFailed())); + + if (m_playlist->isReadOnly()) { + m_readOnly = true; + emit readOnlyChanged(); + } +} + +void QDeclarativePlaylist::componentComplete() +{ +} + +/*! + \qmlsignal QtMultimedia::Audio::itemAboutToBeInserted(start, end) + + This signal is emitted when items are to be inserted into the playlist at \a start and ending at + \a end. + + The corresponding handler is \c onItemAboutToBeInserted. +*/ + +/*! + \qmlsignal QtMultimedia::Audio::itemInserted(start, end) + + This signal is emitted after items have been inserted into the playlist. The new items are those + between \a start and \a end inclusive. + + The corresponding handler is \c onItemInserted. +*/ + +/*! + \qmlsignal QtMultimedia::Audio::itemAboutToBeRemoved(start, end) + + This signal emitted when items are to be deleted from the playlist at \a start and ending at + \a end. + + The corresponding handler is \c onItemAboutToBeRemoved. +*/ + +/*! + \qmlsignal QtMultimedia::Audio::itemRemoved(start, end) + + This signal is emitted after items have been removed from the playlist. The removed items are + those between \a start and \a end inclusive. + + The corresponding handler is \c onMediaRemoved. +*/ + +/*! + \qmlsignal QtMultimedia::Audio::itemChanged(start, end) + + This signal is emitted after items have been changed in the playlist between \a start and + \a end positions inclusive. + + The corresponding handler is \c onItemChanged. +*/ + +/*! + \qmlsignal QtMultimedia::Audio::loaded() + + This signal is emitted when the playlist loading succeeded. + + The corresponding handler is \c onLoaded. +*/ + +/*! + \qmlsignal QtMultimedia::Audio::loadFailed() + + This signal is emitted when the playlist loading failed. \l error and \l errorString can be + checked for more information on the failure. + + The corresponding handler is \c onLoadFailed. +*/ + +QT_END_NAMESPACE + +#include "moc_qdeclarativeplaylist_p.cpp" diff --git a/src/imports/multimedia/qdeclarativeplaylist_p.h b/src/imports/multimedia/qdeclarativeplaylist_p.h new file mode 100644 index 000000000..fd94135e6 --- /dev/null +++ b/src/imports/multimedia/qdeclarativeplaylist_p.h @@ -0,0 +1,199 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEPLAYLIST_P_H +#define QDECLARATIVEPLAYLIST_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/QAbstractListModel> +#include <QtQml/qqmlparserstatus.h> +#include <QtQml/qqml.h> + +#include <qmediaplaylist.h> + +QT_BEGIN_NAMESPACE + +class QDeclarativePlaylistItem : public QObject +{ + Q_OBJECT + Q_PROPERTY(QUrl source READ source WRITE setSource) + +public: + QDeclarativePlaylistItem(QObject *parent = 0); + + QUrl source() const; + void setSource(const QUrl &source); + +private: + QUrl m_source; +}; + +class QDeclarativePlaylist : public QAbstractListModel, public QQmlParserStatus +{ + Q_OBJECT + Q_PROPERTY(PlaybackMode playbackMode READ playbackMode WRITE setPlaybackMode NOTIFY playbackModeChanged) + Q_PROPERTY(QUrl currentItemSource READ currentItemSource NOTIFY currentItemSourceChanged) + Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) + Q_PROPERTY(int itemCount READ itemCount NOTIFY itemCountChanged) + Q_PROPERTY(bool readOnly READ readOnly NOTIFY readOnlyChanged) + Q_PROPERTY(Error error READ error NOTIFY errorChanged) + Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged) + Q_PROPERTY(QQmlListProperty<QDeclarativePlaylistItem> items READ items DESIGNABLE false) + Q_ENUMS(PlaybackMode) + Q_ENUMS(Error) + Q_INTERFACES(QQmlParserStatus) + Q_CLASSINFO("DefaultProperty", "items") + +public: + enum PlaybackMode + { + CurrentItemOnce = QMediaPlaylist::CurrentItemOnce, + CurrentItemInLoop = QMediaPlaylist::CurrentItemInLoop, + Sequential = QMediaPlaylist::Sequential, + Loop = QMediaPlaylist::Loop, + Random = QMediaPlaylist::Random + }; + enum Error + { + NoError = QMediaPlaylist::NoError, + FormatError = QMediaPlaylist::FormatError, + FormatNotSupportedError = QMediaPlaylist::FormatNotSupportedError, + NetworkError = QMediaPlaylist::NetworkError, + AccessDeniedError = QMediaPlaylist::AccessDeniedError + }; + enum Roles + { + SourceRole = Qt::UserRole + 1 + }; + + QDeclarativePlaylist(QObject *parent = 0); + ~QDeclarativePlaylist(); + + PlaybackMode playbackMode() const; + void setPlaybackMode(PlaybackMode playbackMode); + QUrl currentItemSource() const; + int currentIndex() const; + void setCurrentIndex(int currentIndex); + int itemCount() const; + bool readOnly() const; + Error error() const; + QString errorString() const; + QMediaPlaylist *mediaPlaylist() const { return m_playlist; } + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QHash<int, QByteArray> roleNames() const; + + void classBegin(); + void componentComplete(); + + QQmlListProperty<QDeclarativePlaylistItem> items() { + return QQmlListProperty<QDeclarativePlaylistItem>( + this, 0, item_append, item_count, 0, item_clear); + } + static void item_append(QQmlListProperty<QDeclarativePlaylistItem> *list, + QDeclarativePlaylistItem* item) { + static_cast<QDeclarativePlaylist*>(list->object)->addItem(item->source()); + } + static int item_count(QQmlListProperty<QDeclarativePlaylistItem> *list) { + return static_cast<QDeclarativePlaylist*>(list->object)->itemCount(); + } + static void item_clear(QQmlListProperty<QDeclarativePlaylistItem> *list) { + static_cast<QDeclarativePlaylist*>(list->object)->clear(); + } + +public Q_SLOTS: + QUrl itemSource(int index); + int nextIndex(int steps = 1); + int previousIndex(int steps = 1); + void next(); + void previous(); + void shuffle(); + void load(const QUrl &location, const QString &format = QString()); + bool save(const QUrl &location, const QString &format = QString()); + bool addItem(const QUrl &source); + bool insertItem(int index, const QUrl &source); + bool removeItem(int index); + bool clear(); + +Q_SIGNALS: + void playbackModeChanged(); + void currentItemSourceChanged(); + void currentIndexChanged(); + void itemCountChanged(); + void readOnlyChanged(); + void errorChanged(); + + void itemAboutToBeInserted(int start, int end); + void itemInserted(int start, int end); + void itemAboutToBeRemoved(int start, int end); + void itemRemoved(int start, int end); + void itemChanged(int start, int end); + void loaded(); + void loadFailed(); + + void error(QDeclarativePlaylist::Error error, const QString &errorString); + +private Q_SLOTS: + void _q_mediaAboutToBeInserted(int start, int end); + void _q_mediaInserted(int start, int end); + void _q_mediaAboutToBeRemoved(int start, int end); + void _q_mediaRemoved(int start, int end); + void _q_mediaChanged(int start, int end); + void _q_loadFailed(); + +private: + Q_DISABLE_COPY(QDeclarativePlaylist) + + QMediaPlaylist *m_playlist; + QString m_errorString; + QMediaPlaylist::Error m_error; + bool m_readOnly; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QT_PREPEND_NAMESPACE(QDeclarativePlaylistItem)) +QML_DECLARE_TYPE(QT_PREPEND_NAMESPACE(QDeclarativePlaylist)) + +#endif |