The VolumeModule class acts as the interface between the QML-based UI and the QPPS library. This C++ class exposes the volume level, which is read through PPS, as a Q_PROPERTY consumable by QML.
#ifndef VOLUMEMODULE_H #define VOLUMEMODULE_H #include <QObject> #include "qpps/object.h" class VolumeModule : public QObject { Q_OBJECT // Volume setting, accessible by QML Q_PROPERTY(double volume READ volume WRITE setVolume NOTIFY volumeChanged) public: // Constructor explicit VolumeModule(QObject *parent = NULL); Q_INVOKABLE double volume() const; Q_INVOKABLE void setVolume(const double value) const; public Q_SLOTS: // Updates volume level when volume change is reported by PPS void audioStatusChanged(const QString &name, const QPps::Variant &attribute); Q_SIGNALS: // Emitted when the volume level changes void volumeChanged(); private: // Reference to PPS object containing audio volume level QPps::Object *m_ppsAudioStatus; // Volume setting double m_volume; }; #endif // VOLUMEMODULE_H
#include "volumemodule.h" VolumeModule::VolumeModule(QObject *parent) : QObject(parent) { // Access PPS object that stores audio device status m_ppsAudioStatus = new QPps::Object( QStringLiteral("/pps/services/audio/status"), QPps::Object::PublishAndSubscribeMode, false, this); if (!m_ppsAudioStatus->isValid()) { // Print error message if unable to read audio device // status through PPS qCritical("%s Could not open %s: %s", Q_FUNC_INFO, qPrintable(m_ppsAudioStatus->path()), qPrintable(m_ppsAudioStatus->errorString())); } else { // Connect signal for changed attribute in PPS object // to handler for audio status changes connect(m_ppsAudioStatus, SIGNAL(attributeChanged(QString,QPps::Variant)), this, SLOT(audioStatusChanged(QString,QPps::Variant))); } } double VolumeModule::volume() const { return m_volume; } void VolumeModule::setVolume(const double value) const { if (value == m_volume) { //Don't set the volume if it's already set to that return; } if (!m_ppsAudioStatus->isValid()) { qCritical("%s Could not write %s: %s", Q_FUNC_INFO, qPrintable(m_ppsAudioStatus->path()), qPrintable(m_ppsAudioStatus->errorString())); return; } if (!m_ppsAudioStatus->setAttribute( "output.speaker.volume", value)) { qWarning("%s SetAttribute failed %s: %s", Q_FUNC_INFO, qPrintable(m_ppsAudioStatus->path()), qPrintable(m_ppsAudioStatus->errorString())); } } void VolumeModule::audioStatusChanged( const QString &name, const QPps::Variant &attribute) { if (name == QStringLiteral("output.speaker.volume")) { m_volume = attribute.toDouble(); emit volumeChanged(); } }
#include <QtGui/QGuiApplication> #include <QtQuick/QQuickView> #include <QScreen> #include <QQmlContext> #include <qqml.h> // BEGIN NEW CODE #include "volumemodule.h" void setupVolumeModule(QQuickView* view) { // Register with the Qt Metatype system qmlRegisterUncreatableType<VolumeModule>( "com.mycompany.hmi", 1, 0, "VolumeModule", QStringLiteral("Access to object")); // By passing in the view as a parent object, the // VolumeModule will be deleted when its parent is deleted VolumeModule* volumeModule = new VolumeModule(view); // Give the view access to the VolumeModule view->rootContext()->setContextProperty( QStringLiteral("_volumeModule"), volumeModule); } // END NEW CODE int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); // Get the screens so we can dynamically size our display QList<QScreen*> screens = QGuiApplication::screens(); // Quit if no screen is connected if (screens.empty()) { return 1; } // Get the width and height of the display int w = screens[0]->size().width(); int h = screens[0]->size().height(); QQuickView view; // BEGIN NEW CODE // Set up the volume control setupVolumeModule(&view); // END NEW CODE // Set the main QML UI file to this view view.setSource(QUrl("qrc:/qml/main.qml")); // Set up the view to have the proper size view.setResizeMode(QQuickView::SizeRootObjectToView); view.resize(w, h); // Show our user interface view.show(); return app.exec(); }