I've recently started working with Qt and am trying to play a sound file using QMediaPlayer.
My program compiles and runs but the sound file is not played, the QMediaPlayer seems stuck in the QMediaPlayer::LoadingMedia state.
Also - and possibly related - the QMediaPlayer doesn't ever seem to emit its mediaStatusChanged or its error signals (though perhaps this is me not connecting them properly?)
When I run the program as below, it reaches the while loop and never leaves. If I query for player->mediaStatus() inside the loop, it constantly returns 2 (QMediaPlayer::LoadingMedia).
When I run it with the while loop omitted, the program continues to run until it reaches end of execution with no run-time errors but - as you may expect - the file is not played.
Interestingly, the two couts before the while loop, which report player's mediaStatus and state show that the mediaStatus changes from 1 (in the first instance, before setting the media) to 2 (after setting the media) but my ChangedStatus slot is never called, despite connecting to the mediaStatusChanged at the start of the run function.
Running: Debian Jessie, Qt5.7/Qt5.9
AudioPlayer.h
#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.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;
}
main.cpp:
#include "audioplayer.h"
using namespace std;
int main()
{
cout << "Hello World!" << endl;
AudioPlayer myAudioPlayer;
myAudioPlayer.start();
std::cout << "myAudioPlayer started. Waiting...." << std::endl;
myAudioPlayer.wait();
std::cout << "myAudioPlayer returned." << std::endl;
return 0;
}
Extra Info:
Now, initially, I hadn't used QThread and was trying to do this all in main.cpp (just declaring a QMediaPlayer and attempting to set the media and play) but this was giving me QObject::startTimer: timers cannot be started from another thread warning run-time errors in a couple of places (declaration of the QMediaPlayer and, I think, the play command), so I adopted the above approach - although I'm not sure that subclassing QThread is, necessarily, the best way. This is also why everything (declarations etc.) is done in the run function - having the QMediaPlayer as a member of AudioPlayer and initialising it in the constructor gave the same error.
I have compiled and run Qt's Player example (from multimediawidgets) and, by browsing and selecting my test.wav, it can play the file so I don't think it's a compatibility issue. I looked through the Player example source but couldn't see anything jumping out which I had missed and which looked like the cause of my problem.