This is an example audio/video player using QtGStreamer.
In this example, the GStreamer playbin2 element is used to perform most of the tasks. Our code is mostly integrating the UI with the pipeline, handling state changes, doing queries to learn about the position and duration of the stream, performing seeking, etc...
#include "player.h"
#include <QDir>
#include <QUrl>
#include <QGlib/Connect>
#include <QGlib/Error>
#include <QGst/Pipeline>
#include <QGst/ElementFactory>
#include <QGst/Bus>
#include <QGst/Message>
#include <QGst/Query>
#include <QGst/ClockTime>
#include <QGst/Event>
#include <QGst/StreamVolume>
Player::Player(QWidget *parent)
:
QGst::Ui::VideoWidget(parent)
{
connect(&m_positionTimer, SIGNAL(timeout()), this, SIGNAL(positionChanged()));
}
Player::~Player()
{
if (m_pipeline) {
m_pipeline->setState(QGst::StateNull);
stopPipelineWatch();
}
}
void Player::setUri(const QString & uri)
{
QString realUri = uri;
if (realUri.indexOf("://") < 0) {
realUri = QUrl::fromLocalFile(realUri).toEncoded();
}
if (!m_pipeline) {
if (m_pipeline) {
watchPipeline(m_pipeline);
bus->addSignalWatch();
} else {
qCritical() << "Failed to create the pipeline";
}
}
if (m_pipeline) {
m_pipeline->setProperty("uri", realUri);
}
}
QTime Player::position() const
{
if (m_pipeline) {
m_pipeline->query(query);
} else {
return QTime(0,0);
}
}
void Player::setPosition(const QTime & pos)
{
1.0, QGst::FormatTime, QGst::SeekFlagFlush,
);
m_pipeline->sendEvent(evt);
}
int Player::volume() const
{
if (m_pipeline) {
if (svp) {
return svp->volume(QGst::StreamVolumeFormatCubic) * 10;
}
}
return 0;
}
void Player::setVolume(int volume)
{
if (m_pipeline) {
if(svp) {
svp->setVolume((double)volume / 10, QGst::StreamVolumeFormatCubic);
}
}
}
QTime Player::length() const
{
if (m_pipeline) {
m_pipeline->query(query);
} else {
return QTime(0,0);
}
}
QGst::State Player::state() const
{
return m_pipeline ? m_pipeline->currentState() : QGst::StateNull;
}
void Player::play()
{
if (m_pipeline) {
m_pipeline->setState(QGst::StatePlaying);
}
}
void Player::pause()
{
if (m_pipeline) {
m_pipeline->setState(QGst::StatePaused);
}
}
void Player::stop()
{
if (m_pipeline) {
m_pipeline->setState(QGst::StateNull);
Q_EMIT stateChanged();
}
}
{
switch (message->type()) {
case QGst::MessageEos:
stop();
break;
case QGst::MessageError:
stop();
break;
case QGst::MessageStateChanged:
if (message->source() == m_pipeline) {
}
break;
default:
break;
}
}
{
switch (scm->newState()) {
case QGst::StatePlaying:
m_positionTimer.start(100);
break;
case QGst::StatePaused:
if(scm->oldState() == QGst::StatePlaying) {
m_positionTimer.stop();
}
break;
default:
break;
}
Q_EMIT stateChanged();
}
#include "moc_player.cpp"
RefPointer< X > staticCast() const
RefPointer< X > dynamicCast() const
A datatype to hold a time, measured in nanoseconds.
static ClockTime fromTime(const QTime &time)
static const quint64 None
Wrapper class for messages of type QGst::MessageError.
Wrapper class for GstPipeline.
Wrapper class for messages of type QGst::MessageStateChanged.
Wrapper class for GstStreamVolume.
bool connect(void *instance, const char *detailedSignal, T *receiver, R(T::*slot)(Args...), ConnectFlags flags=0)
Wrappers for GStreamer classes.
#include "mediaapp.h"
#include "player.h"
#include <QBoxLayout>
#include <QFileDialog>
#include <QToolButton>
#include <QLabel>
#include <QSlider>
#include <QMouseEvent>
MediaApp::MediaApp(QWidget *parent)
: QWidget(parent)
{
m_player = new Player(this);
connect(m_player, SIGNAL(positionChanged()), this, SLOT(onPositionChanged()));
connect(m_player, SIGNAL(stateChanged()), this, SLOT(onStateChanged()));
m_baseDir = QLatin1String(".");
m_fullScreenTimer.setSingleShot(true);
connect(&m_fullScreenTimer, SIGNAL(timeout()), this, SLOT(hideControls()));
QVBoxLayout *appLayout = new QVBoxLayout;
appLayout->setContentsMargins(0, 0, 0, 0);
createUI(appLayout);
setLayout(appLayout);
onStateChanged();
setWindowTitle(tr("QtGStreamer example player"));
resize(400, 400);
}
MediaApp::~MediaApp()
{
delete m_player;
}
void MediaApp::openFile(const QString & fileName)
{
m_baseDir = QFileInfo(fileName).path();
m_player->stop();
m_player->setUri(fileName);
m_player->play();
}
void MediaApp::open()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open a Movie"), m_baseDir);
if (!fileName.isEmpty()) {
openFile(fileName);
}
}
void MediaApp::toggleFullScreen()
{
if (isFullScreen()) {
setMouseTracking(false);
m_player->setMouseTracking(false);
m_fullScreenTimer.stop();
showControls();
showNormal();
} else {
setMouseTracking(true);
m_player->setMouseTracking(true);
hideControls();
showFullScreen();
}
}
void MediaApp::onStateChanged()
{
QGst::State newState = m_player->state();
m_playButton->setEnabled(newState != QGst::StatePlaying);
m_pauseButton->setEnabled(newState == QGst::StatePlaying);
m_stopButton->setEnabled(newState != QGst::StateNull);
m_positionSlider->setEnabled(newState != QGst::StateNull);
m_volumeSlider->setEnabled(newState != QGst::StateNull);
m_volumeLabel->setEnabled(newState != QGst::StateNull);
m_volumeSlider->setValue(m_player->volume());
if (newState == QGst::StateNull) {
onPositionChanged();
}
}
void MediaApp::onPositionChanged()
{
QTime length(0,0);
QTime curpos(0,0);
if (m_player->state() != QGst::StateReady &&
m_player->state() != QGst::StateNull)
{
length = m_player->length();
curpos = m_player->position();
}
m_positionLabel->setText(curpos.toString("hh:mm:ss.zzz")
+ "/" +
length.toString("hh:mm:ss.zzz"));
if (length != QTime(0,0)) {
m_positionSlider->setValue(curpos.msecsTo(QTime(0,0)) * 1000 / length.msecsTo(QTime(0,0)));
} else {
m_positionSlider->setValue(0);
}
if (curpos != QTime(0,0)) {
m_positionLabel->setEnabled(true);
m_positionSlider->setEnabled(true);
}
}
void MediaApp::setPosition(int value)
{
uint length = -m_player->length().msecsTo(QTime(0,0));
if (length != 0 && value > 0) {
QTime pos(0,0);
pos = pos.addMSecs(length * (value / 1000.0));
m_player->setPosition(pos);
}
}
void MediaApp::showControls(bool show)
{
m_openButton->setVisible(show);
m_playButton->setVisible(show);
m_pauseButton->setVisible(show);
m_stopButton->setVisible(show);
m_fullScreenButton->setVisible(show);
m_positionSlider->setVisible(show);
m_volumeSlider->setVisible(show);
m_volumeLabel->setVisible(show);
m_positionLabel->setVisible(show);
}
void MediaApp::mouseMoveEvent(QMouseEvent *event)
{
Q_UNUSED(event);
if (isFullScreen()) {
showControls();
m_fullScreenTimer.start(3000);
}
}
QToolButton *MediaApp::initButton(QStyle::StandardPixmap icon, const QString & tip,
QObject *dstobj, const char *slot_method, QLayout *layout)
{
QToolButton *button = new QToolButton;
button->setIcon(style()->standardIcon(icon));
button->setIconSize(QSize(36, 36));
button->setToolTip(tip);
connect(button, SIGNAL(clicked()), dstobj, slot_method);
layout->addWidget(button);
return button;
}
void MediaApp::createUI(QBoxLayout *appLayout)
{
appLayout->addWidget(m_player);
m_positionLabel = new QLabel();
m_positionSlider = new QSlider(Qt::Horizontal);
m_positionSlider->setTickPosition(QSlider::TicksBelow);
m_positionSlider->setTickInterval(10);
m_positionSlider->setMaximum(1000);
connect(m_positionSlider, SIGNAL(sliderMoved(int)), this, SLOT(setPosition(int)));
m_volumeSlider = new QSlider(Qt::Horizontal);
m_volumeSlider->setTickPosition(QSlider::TicksLeft);
m_volumeSlider->setTickInterval(2);
m_volumeSlider->setMaximum(10);
m_volumeSlider->setMaximumSize(64,32);
connect(m_volumeSlider, SIGNAL(sliderMoved(int)), m_player, SLOT(setVolume(int)));
QGridLayout *posLayout = new QGridLayout;
posLayout->addWidget(m_positionLabel, 1, 0);
posLayout->addWidget(m_positionSlider, 1, 1, 1, 2);
appLayout->addLayout(posLayout);
QHBoxLayout *btnLayout = new QHBoxLayout;
btnLayout->addStretch();
m_openButton = initButton(QStyle::SP_DialogOpenButton, tr("Open File"),
this, SLOT(open()), btnLayout);
m_playButton = initButton(QStyle::SP_MediaPlay, tr("Play"),
m_player, SLOT(play()), btnLayout);
m_pauseButton = initButton(QStyle::SP_MediaPause, tr("Pause"),
m_player, SLOT(pause()), btnLayout);
m_stopButton = initButton(QStyle::SP_MediaStop, tr("Stop"),
m_player, SLOT(stop()), btnLayout);
m_fullScreenButton = initButton(QStyle::SP_TitleBarMaxButton, tr("Fullscreen"),
this, SLOT(toggleFullScreen()), btnLayout);
btnLayout->addStretch();
m_volumeLabel = new QLabel();
m_volumeLabel->setPixmap(
style()->standardIcon(QStyle::SP_MediaVolume).pixmap(QSize(32, 32),
QIcon::Normal, QIcon::On));
btnLayout->addWidget(m_volumeLabel);
btnLayout->addWidget(m_volumeSlider);
appLayout->addLayout(btnLayout);
}
#include "moc_mediaapp.cpp"