Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Cast a QObject* to QMediaPlayer with qobject_cast



  • Goodmorning,
    I'm trying to cast a QObject pointer taken from QML into a QMediaPlayer one. I always get null using the method qobject_cast.

    Here's the QML code, where volumeMeter has been made available to QML with context->setContextProperty("volumeMeter", &volume); from an object made in main.cpp

        MediaPlayer {
            id: playMusic
            objectName: "playMusic"
            autoLoad: true
            autoPlay: true
            playlist: Playlist{id:playerList}
            Component.onCompleted: { volumeMeter.initVolume(playMusic)}
        }
    

    and here the volumeLevel class:

    #ifndef VOLUMELEVEL_H
    #define VOLUMELEVEL_H
    
    #include <QObject>
    #include <QAudioProbe>
    #include <QMediaPlayer>
    #include <QTimer>
    #include <vector>
    #include <memory>
    
    #include "playListModel_global.h"
    
    class PLAYLISTMODEL_EXPORT VolumeLevel : public QObject
    {
    
        Q_OBJECT
    public:
        explicit VolumeLevel(QObject *parent = nullptr);
        ~VolumeLevel();
    
        // Must call Q_INVOKABLE so that this function can be used in QML
        Q_INVOKABLE void initVolume(QObject* obj);
        void initVolume(QString qmlObjectName);
    
    public slots:
        void processBuffer(QAudioBuffer buffer);
        void timerExpired();
    
    private:
        QAudioProbe m_probe;
        QTimer m_timer;
        QMediaPlayer *m_player;
    };
    
    #include "volumelevel.h"
    #include <QDebug>
    
    #include <QAudioProbe>
    
    VolumeLevel::VolumeLevel(QObject *parent) :
        QObject(parent)
    {
        qRegisterMetaType<QMediaPlayer*>("QMediaPlayer");
    }
    
    void VolumeLevel::initVolume(QString qmlObjectName)
    {
        Q_UNUSED(qmlObjectName)
    }
    
    void VolumeLevel::initVolume(QObject* obj)
    {
        qDebug()<<obj;
        m_player = qobject_cast<QMediaPlayer*>(obj);
        if( m_player != nullptr )
        {
            qDebug()<<m_player;
    
            if(m_probe.setSource(m_player)) {
                connect(&m_probe, &QAudioProbe::audioBufferProbed, this, &VolumeLevel::processBuffer);
                connect(&m_timer, &QTimer::timeout, this, &VolumeLevel::timerExpired);
                m_timer.start(2000);
                qDebug()<<"Connection done";
            }
            else
                qDebug()<<"Connection not done";
        }
        else
            qDebug()<<"cast wrong";
    }
    
    void VolumeLevel::processBuffer(QAudioBuffer buffer)
    {
        // With a 16bit sample buffer:
        const quint16 *data = buffer.constData<quint16>();
        qDebug()<<"Raw: "<<*data;
    }
    
    void VolumeLevel::timerExpired()
    {
        qDebug()<<"probe is active: "<<m_probe.isActive();
    }
    
    VolumeLevel::~VolumeLevel()
    {}
    
    

    The output from console is:
    QDeclarativeAudio(0x142c458, name = "playMusic")
    cast wrong

    So the object is correctly identify but the cast fails..
    Can you advice?

    Thanks.
    Regards, Davide



  • Foudn solution here:
    https://doc.qt.io/qt-5/qml-qtmultimedia-mediaplayer.html

    QObject *qmlMediaPlayer; // The QML MediaPlayer object
    QMediaPlayer *player = qvariant_cast<QMediaPlayer *>(qmlMediaPlayer->property("mediaObject"));

    Thank you


  • Lifetime Qt Champion

    @davidino QDeclarativeAudio is not QMediaPlayer.
    Shouldn't you cast to QDeclarativeAudio?



  • Hello @jsulm,
    thank you for your answer.
    As you can see in the code after the cast, m_probe.setSource() is called which requires QMediaObject* type as parameter.
    QMediaPlayer subclasses QMediaObject, while QDeclarativeAudio doesn't.
    Besides I'm not sure that I can use QDeclarativeAudio so unwary considering that in the class QDeclarativeAudio it's written:

    //
    // 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.
    //

    Does it means that I cannot create in QML a MediaPlayer and pass it to c++ as QMediaPlayer?
    Do I have to create a QMediaPlayer in c++ and then register the class for its usage in QML? It would be crazy..


  • Lifetime Qt Champion

    @davidino said in Cast a QObject* to QMediaPlayer with qobject_cast:

    Do I have to create a QMediaPlayer in c++ and then register the class for its usage in QML? It would be crazy..

    I'm not a QML expert but I think so, yes. I don't think MediaPlayer in QML is same as QMediaPlayer, but I may be wrong...



  • Foudn solution here:
    https://doc.qt.io/qt-5/qml-qtmultimedia-mediaplayer.html

    QObject *qmlMediaPlayer; // The QML MediaPlayer object
    QMediaPlayer *player = qvariant_cast<QMediaPlayer *>(qmlMediaPlayer->property("mediaObject"));

    Thank you


Log in to reply