Akiva Akiva - 1 day ago 4
C++ Question

Why is QMediaPlayer::duration() giving me a value of -1?

Here is my code:

QString BoatProgramming::setDuration(QString path)
{
if (path.isNull()) { return ""; }
QMediaPlayer mp;
mp.setMedia(QUrl::fromLocalFile("/home/akiva/deleteme.ogg"));
qDebug() << mp.duration(); // Outputting a value of -1

m_Duration = QString::number(mp.duration());
emit durationChanged();
return m_Duration;
}


There is obviously an error somewhere, but beyond checking the filename, I am lamentably amiss as to what the problem is. Could it be simply that
.ogg
is not supported? Am I calling the function before the object is fully loaded into memory? Or is it something else?

Thanks.

Answer

QMediaPlayer::setMedia() performs loading asynchronously, from the docs:

This function returns immediately after recording the specified source of the media. It does not wait for the media to finish loading and does not check for errors. Listen for the mediaStatusChanged() and error() signals to be notified when the media is loaded and when an error occurs during loading.

This means that querying QMediaPlayer for duration() after calling setMedia() immediately may not work, since QMediaPlayer might not have loaded the media yet.

In order to guarantee that loading has finished before calling duration(), you have to listen for mediaStatusChanged() signal, and get duration() only when mediaStatus() returns QMediaPlayer::LoadedMedia. Here is a minimal example:

#include <QtWidgets>
#include <QtMultimedia>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    QLabel label; //a label to display duration

    QString fileName = QFileDialog::getOpenFileName(nullptr, "Open Media File");

    QMediaPlayer mp;
    mp.setMedia(QUrl::fromLocalFile(fileName));
    QObject::connect(&mp, &QMediaPlayer::mediaStatusChanged,
                     [&](QMediaPlayer::MediaStatus status){
        if(status == QMediaPlayer::LoadedMedia) //when loading is finished
        {
            //show duration in a label
            qint64 duration= mp.duration();
            label.setText(QString("Duration: %1 ms.\n\nThat is: %2")
                          .arg(duration)
                          .arg(QDateTime::fromTime_t(duration/1000).toUTC()
                               .toString("hh:mm:ss")));
            label.show();
        }
    });

    return app.exec();
}
Comments