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 cout
s 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 connect
ing 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.
QApplication
is explicitely not used either. It is silently assumed that "QApplication" and corresponding message loop is always present. – bkausbk