2016-11-30 82 views
0

这里是我的代码:为什么QMediaPlayer :: duration()给我的值为-1?

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; 
} 

显然有错误的地方,但除了检查文件名,我来的问题是什么可悲的不妥。难道简单地说.ogg不支持?我是否在对象完全加载到内存之前调用该函数?或者是别的什么?

谢谢。

回答

1

QMediaPlayer::setMedia()执行异步加载,从docs

该函数记录中指定的媒体的源后立即返回。它不会等待媒体完成加载,也不会检查错误。收听媒体加载时和加载过程中发生错误时通知mediaStatusChanged()error()信号。

这意味着立即调用setMedia()后查询QMediaPlayerduration()可能无法正常工作,因为QMediaPlayer可能没有加载的媒体呢。

为了保证装载调用duration()之前已经完成,你必须听mediaStatusChanged()信号,并获得duration()只有当mediaStatus()回报QMediaPlayer::LoadedMedia。这里是一个最小的例子:

#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(); 
} 
+0

这个问题我认为是不同的。在主代码中尝试代码之后,事情就会顺利进行,所以你的代码可以工作。然而,在我自己的班级尝试,我可以等待一年,而且这个信号永远不会触发。然而,把它改成这样:'QObject :: connect(&m_MediaPlayer,&QMediaPlayer :: durationChanged,[&](qint64 fun)'' – Akiva

+0

顺便说一句,我尝试了使用Google搜索,但对于我的爱我无法找到任何关于它的语法''[&]'都做了什么?我从来没有见过这样的东西。 – Akiva

+1

@Akiva,这是一个C++ 11 lambda表达式,请参阅[this question](http://stackoverflow.com/*/7627098/2666212)。[&]'语法通过引用捕获lambda使用的变量。不要**在你的类的方法中为局部变量做这些事情,你最终会使用dangling引用你的lambda(这可能是事情在main中工作的原因,但不在你的类中)如果你不习惯lambda表达式,使用普通的slot来避免这样的问题(例如,用一个普通的slot替换lambda函数)在你的班级中定义) – Mike

相关问题