summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrever Fischer <wm161@wm161.net>2013-05-09 14:17:09 (GMT)
committerTrever Fischer <wm161@wm161.net>2013-05-09 14:17:09 (GMT)
commit65316e44b644967a3eeb516190b60c1f62c128d7 (patch)
tree0eb1a3654d1885afaeb8edf2ef4e39a434904a6a
parentd5696b0122cd80b623cd4d16d20db4a4b3183344 (diff)
downloadgst-sdk-tutorials-65316e44b644967a3eeb516190b60c1f62c128d7.tar.gz
gst-sdk-tutorials-65316e44b644967a3eeb516190b60c1f62c128d7.tar.xz
Add player and appsink-src examplesHEADmaster
-rw-r--r--gst-sdk/tutorials/qt/appsink-src/CMakeLists.txt13
-rw-r--r--gst-sdk/tutorials/qt/appsink-src/main.cpp131
-rw-r--r--gst-sdk/tutorials/qt/player/CMakeLists.txt15
-rw-r--r--gst-sdk/tutorials/qt/player/main.cpp38
-rw-r--r--gst-sdk/tutorials/qt/player/mediaapp.cpp251
-rw-r--r--gst-sdk/tutorials/qt/player/mediaapp.h81
-rw-r--r--gst-sdk/tutorials/qt/player/player.cpp213
-rw-r--r--gst-sdk/tutorials/qt/player/player.h61
8 files changed, 803 insertions, 0 deletions
diff --git a/gst-sdk/tutorials/qt/appsink-src/CMakeLists.txt b/gst-sdk/tutorials/qt/appsink-src/CMakeLists.txt
new file mode 100644
index 0000000..33d731f
--- /dev/null
+++ b/gst-sdk/tutorials/qt/appsink-src/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 2.8)
+find_package(QtGStreamer REQUIRED)
+find_package(Qt5Core REQUIRED)
+find_package(Qt5Widgets REQUIRED)
+set(CMAKE_AUTOMOC TRUE)
+
+include_directories(${QTGSTREAMER_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}
+ ${Qt5Core_INCLUDE_DIRS})
+add_definitions(${QTGSTREAMER_DEFINITIONS})
+set(CMAKE_CXX_FLAGS "-fPIE ${CMAKE_CXX_FLAGS} ${QTGSTREAMER_FLAGS}")
+
+add_executable(appsink-src main.cpp)
+target_link_libraries(appsink-src ${QTGSTREAMER_UTILS_LIBRARIES} ${Qt5Core_LIBRARIES})
diff --git a/gst-sdk/tutorials/qt/appsink-src/main.cpp b/gst-sdk/tutorials/qt/appsink-src/main.cpp
new file mode 100644
index 0000000..ad6a798
--- /dev/null
+++ b/gst-sdk/tutorials/qt/appsink-src/main.cpp
@@ -0,0 +1,131 @@
+/*
+ Copyright (C) 2011 Collabora Ltd. <info@collabora.co.uk>
+ @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <iostream>
+#include <QtCore/QCoreApplication>
+#include <QGlib/Error>
+#include <QGlib/Connect>
+#include <QGst/Init>
+#include <QGst/Bus>
+#include <QGst/Pipeline>
+#include <QGst/Parse>
+#include <QGst/Message>
+#include <QGst/Utils/ApplicationSink>
+#include <QGst/Utils/ApplicationSource>
+
+
+class MySink : public QGst::Utils::ApplicationSink
+{
+public:
+ MySink(QGst::Utils::ApplicationSource *src)
+ : QGst::Utils::ApplicationSink(), m_src(src) {}
+
+protected:
+ virtual void eos()
+ {
+ m_src->endOfStream();
+ }
+
+ virtual QGst::FlowReturn newBuffer()
+ {
+ m_src->pushBuffer(pullBuffer());
+ return QGst::FlowOk;
+ }
+
+private:
+ QGst::Utils::ApplicationSource *m_src;
+};
+
+
+class Player : public QCoreApplication
+{
+public:
+ Player(int argc, char **argv);
+ ~Player();
+
+private:
+ void onBusMessage(const QGst::MessagePtr & message);
+
+private:
+ QGst::Utils::ApplicationSource m_src;
+ MySink m_sink;
+ QGst::PipelinePtr pipeline1;
+ QGst::PipelinePtr pipeline2;
+};
+
+Player::Player(int argc, char **argv)
+ : QCoreApplication(argc, argv), m_sink(&m_src)
+{
+ QGst::init(&argc, &argv);
+
+ if (argc <= 1) {
+ std::cerr << "Usage: " << argv[0] << " <audio_file>" << std::endl;
+ std::exit(1);
+ }
+
+ const char *caps = "audio/x-raw-int,channels=2,rate=48000,"
+ "signed=(boolean)true,width=16,depth=16,endianness=1234";
+
+ /* source pipeline */
+ QString pipe1Descr = QString("filesrc location=\"%1\" ! "
+ "decodebin2 ! "
+ "audioconvert ! "
+ "audioresample ! "
+ "appsink name=\"mysink\" caps=\"%2\"").arg(argv[1], caps);
+ pipeline1 = QGst::Parse::launch(pipe1Descr).dynamicCast<QGst::Pipeline>();
+ m_sink.setElement(pipeline1->getElementByName("mysink"));
+ QGlib::connect(pipeline1->bus(), "message::error", this, &Player::onBusMessage);
+ pipeline1->bus()->addSignalWatch();
+
+ /* sink pipeline */
+ QString pipe2Descr = QString("appsrc name=\"mysrc\" caps=\"%1\" ! autoaudiosink").arg(caps);
+ pipeline2 = QGst::Parse::launch(pipe2Descr).dynamicCast<QGst::Pipeline>();
+ m_src.setElement(pipeline2->getElementByName("mysrc"));
+ QGlib::connect(pipeline2->bus(), "message", this, &Player::onBusMessage);
+ pipeline2->bus()->addSignalWatch();
+
+ /* start playing */
+ pipeline1->setState(QGst::StatePlaying);
+ pipeline2->setState(QGst::StatePlaying);
+}
+
+Player::~Player()
+{
+ pipeline1->setState(QGst::StateNull);
+ pipeline2->setState(QGst::StateNull);
+}
+
+void Player::onBusMessage(const QGst::MessagePtr & message)
+{
+ switch (message->type()) {
+ case QGst::MessageEos:
+ quit();
+ break;
+ case QGst::MessageError:
+ qCritical() << message.staticCast<QGst::ErrorMessage>()->error();
+ break;
+ default:
+ break;
+ }
+}
+
+
+int main(int argc, char **argv)
+{
+ Player p(argc, argv);
+ return p.exec();
+}
diff --git a/gst-sdk/tutorials/qt/player/CMakeLists.txt b/gst-sdk/tutorials/qt/player/CMakeLists.txt
new file mode 100644
index 0000000..5f05b2b
--- /dev/null
+++ b/gst-sdk/tutorials/qt/player/CMakeLists.txt
@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 2.8)
+find_package(QtGStreamer REQUIRED)
+find_package(Qt5Core REQUIRED)
+find_package(Qt5Widgets REQUIRED)
+set(CMAKE_AUTOMOC TRUE)
+
+include_directories(${QTGSTREAMER_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}
+ ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Core_INCLUDE_DIRS})
+add_definitions(${QTGSTREAMER_DEFINITIONS})
+set(CMAKE_CXX_FLAGS "-fPIE ${CMAKE_CXX_FLAGS} ${QTGSTREAMER_FLAGS}")
+
+set(player_SOURCES main.cpp player.cpp mediaapp.cpp)
+
+add_executable(player ${player_SOURCES})
+target_link_libraries(player ${QTGSTREAMER_UI_LIBRARIES} ${Qt5Widgets_LIBRARIES})
diff --git a/gst-sdk/tutorials/qt/player/main.cpp b/gst-sdk/tutorials/qt/player/main.cpp
new file mode 100644
index 0000000..71a6aa4
--- /dev/null
+++ b/gst-sdk/tutorials/qt/player/main.cpp
@@ -0,0 +1,38 @@
+/*
+ Copyright (C) 2010 Marco Ballesio <gibrovacco@gmail.com>
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "mediaapp.h"
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
+#include <QtWidgets/QApplication>
+#else
+#include <QtGui/QApplication>
+#endif
+#include <QGst/Init>
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ QGst::init(&argc, &argv);
+
+ MediaApp media;
+ media.show();
+
+ if (argc == 2) {
+ media.openFile(argv[1]);
+ }
+
+ return app.exec();
+}
diff --git a/gst-sdk/tutorials/qt/player/mediaapp.cpp b/gst-sdk/tutorials/qt/player/mediaapp.cpp
new file mode 100644
index 0000000..22be795
--- /dev/null
+++ b/gst-sdk/tutorials/qt/player/mediaapp.cpp
@@ -0,0 +1,251 @@
+/*
+ Copyright (C) 2010 Marco Ballesio <gibrovacco@gmail.com>
+ Copyright (C) 2011 Collabora Ltd.
+ @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "mediaapp.h"
+#include "player.h"
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
+#include <QtWidgets/QBoxLayout>
+#include <QtWidgets/QFileDialog>
+#include <QtWidgets/QToolButton>
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QSlider>
+#else
+#include <QtGui/QBoxLayout>
+#include <QtGui/QFileDialog>
+#include <QtGui/QToolButton>
+#include <QtGui/QLabel>
+#include <QtGui/QSlider>
+#include <QtGui/QMouseEvent>
+#endif
+
+MediaApp::MediaApp(QWidget *parent)
+ : QWidget(parent)
+{
+ //create the player
+ m_player = new Player(this);
+ connect(m_player, SIGNAL(positionChanged()), this, SLOT(onPositionChanged()));
+ connect(m_player, SIGNAL(stateChanged()), this, SLOT(onStateChanged()));
+
+ //m_baseDir is used to remember the last directory that was used.
+ //defaults to the current working directory
+ m_baseDir = QLatin1String(".");
+
+ //this timer (re-)hides the controls after a few seconds when we are in fullscreen mode
+ m_fullScreenTimer.setSingleShot(true);
+ connect(&m_fullScreenTimer, SIGNAL(timeout()), this, SLOT(hideControls()));
+
+ //create the UI
+ QVBoxLayout *appLayout = new QVBoxLayout;
+ appLayout->setContentsMargins(0, 0, 0, 0);
+ createUI(appLayout);
+ setLayout(appLayout);
+
+ onStateChanged(); //set the controls to their default state
+
+ 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 we are in Null state, call onPositionChanged() to restore
+ //the position of the slider and the text on the label
+ if (newState == QGst::StateNull) {
+ onPositionChanged();
+ }
+}
+
+/* Called when the positionChanged() is received from the player */
+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);
+ }
+}
+
+/* Called when the user changes the slider's position */
+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); //re-hide controls after 3s
+ }
+}
+
+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"
diff --git a/gst-sdk/tutorials/qt/player/mediaapp.h b/gst-sdk/tutorials/qt/player/mediaapp.h
new file mode 100644
index 0000000..24a3d62
--- /dev/null
+++ b/gst-sdk/tutorials/qt/player/mediaapp.h
@@ -0,0 +1,81 @@
+/*
+ Copyright (C) 2010 Marco Ballesio <gibrovacco@gmail.com>
+ Copyright (C) 2011 Collabora Ltd.
+ @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef MEDIAAPP_H
+#define MEDIAAPP_H
+
+#include <QtCore/QTimer>
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
+#include <QtWidgets/QWidget>
+#include <QtWidgets/QStyle>
+#else
+#include <QtGui/QWidget>
+#include <QtGui/QStyle>
+#endif
+
+class Player;
+class QBoxLayout;
+class QLabel;
+class QSlider;
+class QToolButton;
+class QTimer;
+
+class MediaApp : public QWidget
+{
+ Q_OBJECT
+public:
+ MediaApp(QWidget *parent = 0);
+ ~MediaApp();
+
+ void openFile(const QString & fileName);
+
+private Q_SLOTS:
+ void open();
+ void toggleFullScreen();
+
+ void onStateChanged();
+ void onPositionChanged();
+
+ void setPosition(int position);
+
+ void showControls(bool show = true);
+ void hideControls() { showControls(false); }
+
+protected:
+ void mouseMoveEvent(QMouseEvent *event);
+
+private:
+ QToolButton *initButton(QStyle::StandardPixmap icon, const QString & tip,
+ QObject *dstobj, const char *slot_method, QLayout *layout);
+ void createUI(QBoxLayout *appLayout);
+
+ QString m_baseDir;
+ Player *m_player;
+ QToolButton *m_openButton;
+ QToolButton *m_fullScreenButton;
+ QToolButton *m_playButton;
+ QToolButton *m_pauseButton;
+ QToolButton *m_stopButton;
+ QSlider *m_positionSlider;
+ QSlider *m_volumeSlider;
+ QLabel *m_positionLabel;
+ QLabel *m_volumeLabel;
+ QTimer m_fullScreenTimer;
+};
+
+#endif
diff --git a/gst-sdk/tutorials/qt/player/player.cpp b/gst-sdk/tutorials/qt/player/player.cpp
new file mode 100644
index 0000000..bfcd091
--- /dev/null
+++ b/gst-sdk/tutorials/qt/player/player.cpp
@@ -0,0 +1,213 @@
+/*
+ Copyright (C) 2010 Marco Ballesio <gibrovacco@gmail.com>
+ Copyright (C) 2011 Collabora Ltd.
+ @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "player.h"
+#include <QtCore/QDir>
+#include <QtCore/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)
+{
+ //this timer is used to tell the ui to change its position slider & label
+ //every 100 ms, but only when the pipeline is playing
+ 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 uri is not a real uri, assume it is a file path
+ if (realUri.indexOf("://") < 0) {
+ realUri = QUrl::fromLocalFile(realUri).toEncoded();
+ }
+
+ if (!m_pipeline) {
+ m_pipeline = QGst::ElementFactory::make("playbin2").dynamicCast<QGst::Pipeline>();
+ if (m_pipeline) {
+ //let the video widget watch the pipeline for new video sinks
+ watchPipeline(m_pipeline);
+
+ //watch the bus for messages
+ QGst::BusPtr bus = m_pipeline->bus();
+ bus->addSignalWatch();
+ QGlib::connect(bus, "message", this, &Player::onBusMessage);
+ } else {
+ qCritical() << "Failed to create the pipeline";
+ }
+ }
+
+ if (m_pipeline) {
+ m_pipeline->setProperty("uri", realUri);
+ }
+}
+
+QTime Player::position() const
+{
+ if (m_pipeline) {
+ //here we query the pipeline about its position
+ //and we request that the result is returned in time format
+ QGst::PositionQueryPtr query = QGst::PositionQuery::create(QGst::FormatTime);
+ m_pipeline->query(query);
+ return QGst::ClockTime(query->position()).toTime();
+ } else {
+ return QTime(0,0);
+ }
+}
+
+void Player::setPosition(const QTime & pos)
+{
+ QGst::SeekEventPtr evt = QGst::SeekEvent::create(
+ 1.0, QGst::FormatTime, QGst::SeekFlagFlush,
+ QGst::SeekTypeSet, QGst::ClockTime::fromTime(pos),
+ QGst::SeekTypeNone, QGst::ClockTime::None
+ );
+
+ m_pipeline->sendEvent(evt);
+}
+
+int Player::volume() const
+{
+ if (m_pipeline) {
+ QGst::StreamVolumePtr svp =
+ m_pipeline.dynamicCast<QGst::StreamVolume>();
+
+ if (svp) {
+ return svp->volume(QGst::StreamVolumeFormatCubic) * 10;
+ }
+ }
+
+ return 0;
+}
+
+
+void Player::setVolume(int volume)
+{
+ if (m_pipeline) {
+ QGst::StreamVolumePtr svp =
+ m_pipeline.dynamicCast<QGst::StreamVolume>();
+
+ if(svp) {
+ svp->setVolume((double)volume / 10, QGst::StreamVolumeFormatCubic);
+ }
+ }
+}
+
+QTime Player::length() const
+{
+ if (m_pipeline) {
+ //here we query the pipeline about the content's duration
+ //and we request that the result is returned in time format
+ QGst::DurationQueryPtr query = QGst::DurationQuery::create(QGst::FormatTime);
+ m_pipeline->query(query);
+ return QGst::ClockTime(query->duration()).toTime();
+ } 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);
+
+ //once the pipeline stops, the bus is flushed so we will
+ //not receive any StateChangedMessage about this.
+ //so, to inform the ui, we have to emit this signal manually.
+ Q_EMIT stateChanged();
+ }
+}
+
+void Player::onBusMessage(const QGst::MessagePtr & message)
+{
+ switch (message->type()) {
+ case QGst::MessageEos: //End of stream. We reached the end of the file.
+ stop();
+ break;
+ case QGst::MessageError: //Some error occurred.
+ qCritical() << message.staticCast<QGst::ErrorMessage>()->error();
+ stop();
+ break;
+ case QGst::MessageStateChanged: //The element in message->source() has changed state
+ if (message->source() == m_pipeline) {
+ handlePipelineStateChange(message.staticCast<QGst::StateChangedMessage>());
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void Player::handlePipelineStateChange(const QGst::StateChangedMessagePtr & scm)
+{
+ switch (scm->newState()) {
+ case QGst::StatePlaying:
+ //start the timer when the pipeline starts playing
+ m_positionTimer.start(100);
+ break;
+ case QGst::StatePaused:
+ //stop the timer when the pipeline pauses
+ if(scm->oldState() == QGst::StatePlaying) {
+ m_positionTimer.stop();
+ }
+ break;
+ default:
+ break;
+ }
+
+ Q_EMIT stateChanged();
+}
+
+#include "moc_player.cpp"
diff --git a/gst-sdk/tutorials/qt/player/player.h b/gst-sdk/tutorials/qt/player/player.h
new file mode 100644
index 0000000..697887d
--- /dev/null
+++ b/gst-sdk/tutorials/qt/player/player.h
@@ -0,0 +1,61 @@
+/*
+ Copyright (C) 2010 Marco Ballesio <gibrovacco@gmail.com>
+ Copyright (C) 2011 Collabora Ltd.
+ @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef PLAYER_H
+#define PLAYER_H
+
+#include <QtCore/QTimer>
+#include <QtCore/QTime>
+#include <QGst/Pipeline>
+#include <QGst/Ui/VideoWidget>
+
+class Player : public QGst::Ui::VideoWidget
+{
+ Q_OBJECT
+public:
+ Player(QWidget *parent = 0);
+ ~Player();
+
+ void setUri(const QString & uri);
+
+ QTime position() const;
+ void setPosition(const QTime & pos);
+ int volume() const;
+
+ QTime length() const;
+ QGst::State state() const;
+
+public Q_SLOTS:
+ void play();
+ void pause();
+ void stop();
+ void setVolume(int volume);
+
+Q_SIGNALS:
+ void positionChanged();
+ void stateChanged();
+
+private:
+ void onBusMessage(const QGst::MessagePtr & message);
+ void handlePipelineStateChange(const QGst::StateChangedMessagePtr & scm);
+
+ QGst::PipelinePtr m_pipeline;
+ QTimer m_positionTimer;
+};
+
+#endif