C++ QMediaPlayer未加载媒体且未发出mediaStatusChanged()信号
我最近开始使用Qt,并尝试使用QMediaPlayer播放声音文件 我的程序编译并运行,但声音文件未播放,QMediaPlayer似乎卡在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:
QMediaPlayer::LoadingMedia
状态
此外,可能相关的是,QMediaPlayer似乎从未发出其mediaStatusChanged
或错误
信号(尽管可能是我没有正确连接它们?)
当我按如下方式运行程序时,它到达while
循环并且从不离开。如果我在循环中查询player->mediaStatus()
,它会不断返回2(QMediaPlayer::LoadingMedia
)
当我在省略while循环的情况下运行它时,程序将继续运行,直到执行结束,不会出现运行时错误,但正如您所料,文件不会被播放
有趣的是,while
循环前面的两个cout
s报告播放器的mediaStatus
和state
显示mediaStatus
从1(在第一次设置媒体之前)更改为2(在设置媒体之后),但从未调用myChangedStatus
插槽,尽管在运行
功能开始时连接到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播放器示例。请删除QThreadrun
方法中的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);
};