Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ QMediaPlayer未加载媒体且未发出mediaStatusChanged()信号_C++_Qt_Audio_Qt5_Qmediaplayer - Fatal编程技术网

C++ QMediaPlayer未加载媒体且未发出mediaStatusChanged()信号

C++ QMediaPlayer未加载媒体且未发出mediaStatusChanged()信号,c++,qt,audio,qt5,qmediaplayer,C++,Qt,Audio,Qt5,Qmediaplayer,我最近开始使用Qt,并尝试使用QMediaPlayer播放声音文件 我的程序编译并运行,但声音文件未播放,QMediaPlayer似乎卡在QMediaPlayer::LoadingMedia状态 此外,可能相关的是,QMediaPlayer似乎从未发出其mediaStatusChanged或错误信号(尽管可能是我没有正确连接它们?) 当我按如下方式运行程序时,它到达while循环并且从不离开。如果我在循环中查询player->mediaStatus(),它会不断返回2(QMediaPlayer:

我最近开始使用Qt,并尝试使用QMediaPlayer播放声音文件

我的程序编译并运行,但声音文件未播放,QMediaPlayer似乎卡在
QMediaPlayer::LoadingMedia
状态

此外,可能相关的是,QMediaPlayer似乎从未发出其
mediaStatusChanged
错误
信号(尽管可能是我没有正确连接它们?)

当我按如下方式运行程序时,它到达
while
循环并且从不离开。如果我在循环中查询
player->mediaStatus()
,它会不断返回2(
QMediaPlayer::LoadingMedia

当我在省略while循环的情况下运行它时,程序将继续运行,直到执行结束,不会出现运行时错误,但正如您所料,文件不会被播放

有趣的是,
while
循环前面的两个
cout
s报告播放器的
mediaStatus
state
显示
mediaStatus
从1(在第一次设置媒体之前)更改为2(在设置媒体之后),但从未调用my
ChangedStatus
插槽,尽管
运行
功能开始时连接到
mediaStatusChanged

跑步:Debian Jessie,Qt5.7/Qt5.9

音频播放器

#include <QThread>
#include <QMediaPlayer>

class AudioPlayer : public QThread {
    Q_OBJECT

public:
    AudioPlayer();

public slots:
    void ChangedStatus(QMediaPlayer::MediaStatus);
    void MediaError(QMediaPlayer::Error);

protected:
    void run();
};
#包括
#包括
类AudioPlayer:publicQThread{
Q_对象
公众:
音频播放器();
公众时段:
void ChangedStatus(QMediaPlayer::MediaStatus);
void MediaError(QMediaPlayer::Error);
受保护的:
无效运行();
};
AudioPlayer.cpp:

AudioPlayer::AudioPlayer(){}    
void AudioPlayer::run()
{
    QMediaPlayer* player = new QMediaPlayer();
    connect(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(ChangedStatus(QMediaPlayer::MediaStatus)));
    connect(player, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(MediaError(QMediaPlayer::Error)));
    std::cout << "Got player!" << std::endl;

    std::cout << "\n\n\tPlayer state: " << player->state() << "\n\tMediaState: " << player->mediaStatus() << std::endl;

    player->setMedia(QUrl::fromLocalFile("/home/me/test.wav") );
    std::cout << "Set source" << std::endl;

    std::cout << "\n\n\tPlayer state: " << player->state() << "\n\tMediaState: " << player->mediaStatus() << std::endl;

    while(player->mediaStatus() != QMediaPlayer::MediaStatus::LoadedMedia)
    {//
    }

    player->setVolume(100);
    std::cout << "Set volume" << std::endl;

    player->play();
    std::cout << "Played" << std::endl;    
}    
void AudioPlayer::MediaError(QMediaPlayer::Error error)
{
    std::cout << "Media Error: " << error << std::endl;
}    
void AudioPlayer::ChangedStatus(QMediaPlayer::MediaStatus status)
{
    std::cout << "Status changed to: " << status << std::endl;
}
AudioPlayer::AudioPlayer(){}
void AudioPlayer::run()
{
QMediaPlayer*播放器=新的QMediaPlayer();
连接(播放器,信号(mediaStatusChanged(QMediaPlayer::MediaStatus)),此插槽(ChangedStatus(QMediaPlayer::MediaStatus));
连接(播放器,信号(错误(QMediaPlayer::error)),此,插槽(mediaperror(QMediaPlayer::error));

std::cout您应该创建一个QApplication对象并使用它的消息循环。我建议您测试以下内容:

#include "audioplayer.h"

using namespace std;

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);

    AudioPlayer myAudioPlayer;
    myAudioPlayer.start();

    return a.exec();
}
您至少会收到信号。如果媒体状态达到
QMediaPlayer::StoppedState
或出现任何错误,您可以调用
QApplication::instance()->quit()
停止应用程序

编辑:最好使用新样式的连接,如:

connect(player, &QMediaPlayer::mediaStatusChanged, this, &QMediaPlayer::ChangedStatus);
它更可靠,您不必使用
Q\u DECLARE\u METATYPE()

由于
QMediaPlayer
类包含另一个名为
error
的方法,该方法具有不同的签名,因此信号连接有点复杂。这是因为编译器不知道您所指的
error
方法。在这种情况下,
static\u cast
是解决此歧义的方法:

connect(
    player,
    static_cast<void(QMediaPlayer::*)(QMediaPlayer::Error )>(&QMediaPlayer::error),
    this,
    &AudioPlayer::MediaError
);

强制QApplication实例在哪里?没有消息循环,即myAudioPlayer.exec()和QApplication::exec()都不调用Where。因此信号永远无法到达您的插槽。@bkausbk感谢您的帮助-它确实有助于信号正常工作(请参阅下面我对您答案的评论).不幸的是,我没有提到QApplication的必要性(只提到需要创建媒体播放器、设置媒体源和播放),所以我没有意识到这是强制性的。我也没有找到一个明确没有使用
QApplication
的示例。它默认为“QApplication”并且相应的消息循环始终存在。感谢您的输入。这使
mediaStatusChanged
信号按照您所说的方式工作。不幸的是,该文件仍然无法加载-知道原因吗?此外,我无法使用您为mediaStatusChanged信号演示的相同方法连接错误信号。Compiler抱怨“未解决的重载函数类型”-它可能与错误枚举或错误属性混淆了吗?许多人感谢您的进一步建议。到
错误
的连接现在通过
静态\u cast
完成了-尽管没有产生错误。关于该文件,Qt的播放器示例可以打开并播放我试图播放的同一文件se没有问题-这是否意味着我也应该能够播放该文件?如果没有,我从哪里开始查找编解码器?你是说“windows编解码器”就像在Windows操作系统中一样?使用Debian,可能会有什么不同吗?@cprlklege:是的,在您的情况下,它不是Windows操作系统多媒体编解码器,它可能是Linux Qt框架的一部分,也可能是某些操作系统组件的一部分。我不知道。如果您说Qt播放器示例按预期工作,您应该将源代码与h Qt播放器示例。请删除QThread
run
方法中的
while
循环。它不是干净的代码。再次感谢。正如我在最初的问题中提到的,我正在与播放器示例进行比较,但没有任何明显的遗漏。关于while循环,它只是其中的一个在这个调试阶段,直到我可以得到一些工作和播放文件。我将继续编辑我所拥有的,并尝试您最近更新中说明的方法。感谢您到目前为止的帮助。非常感谢!根据您上次的编辑使用插槽和信号,使我能够获得文件加载d和按预期播放。我仍然不是问题背后的100%实际原因,但可能与尝试设置媒体时处于错误线程有关。使用
if(thread()!=QThread::currentThread())
加载
插槽中进行测试-如
播放()所示
slot-似乎解决了这个问题。最后一个问题再次感谢您
connect(
    player,
    static_cast<void(QMediaPlayer::*)(QMediaPlayer::Error )>(&QMediaPlayer::error),
    this,
    &AudioPlayer::MediaError
);
class AudioPlayer : public QThread {
public:
    AudioPlayer() : _Player(nullptr) {
        moveToThread(this); // AudioPlayer object become part of this new thread
    }

public slots:

    void setVolume(int);
    void load(QString Media);
    // ...

    void play() {
        // Never directly access any members since they may belong to a different thread
        if (thread() != QThread::currentThread()) {
            QMetaObject::invokeMethod(this, "play", Qt::QueuedConnection);
        } else {
            _Player->play();
        }
    }

    void stop() {
        quit(); // Quiting thread message loop
    }

private:
    QMediaPlayer* _Player;

    void run() {
        _Player = new QMediaPlayer(this);

        connect(...) // All connections go here...

        int Result = QThread::exec();

        _Player->stop();

        delete _Player;
    }

private slots:

    void HandleStatusChange(QMediaPlayer::MediaStatus Status) {
        emit statusChanged(Status); // Redirect so that the main application can handle this signal too
    }

signals:
    void statusChanged((QMediaPlayer::MediaStatus);
};