summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--cmake/modules/FindQtGstreamer.cmake18
-rw-r--r--codegen/CMakeLists.txt2
-rw-r--r--elements/CMakeLists.txt2
-rw-r--r--src/CMakeLists.txt20
-rw-r--r--src/QGlib/signal.h5
-rw-r--r--src/QGst/Ui/VideoWidget1
-rw-r--r--src/QGst/Ui/videowidget.cpp215
-rw-r--r--src/QGst/Ui/videowidget.h63
-rw-r--r--src/main.dox7
-rw-r--r--tests/manual/CMakeLists.txt5
-rw-r--r--tests/manual/videowidgettest.cpp110
-rw-r--r--tests/manual/videowidgettest.ui170
13 files changed, 610 insertions, 12 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 70e2b7f..ed965ad 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,7 +7,7 @@ set(BUILDING_QTGSTREAMER TRUE)
set(QTGSTREAMER_VERSION 0.1)
set(QTGSTREAMER_SOVERSION 0)
-find_package(Qt4 COMPONENTS QtCore QtTest REQUIRED)
+find_package(Qt4 COMPONENTS QtCore QtGui QtTest REQUIRED)
find_package(QtGstreamer REQUIRED)
find_package(Automoc4 REQUIRED)
find_package(GStreamer REQUIRED)
@@ -21,8 +21,6 @@ if (${GSTREAMER_VERSION} VERSION_LESS "0.10.30")
message(FATAL_ERROR "QtGstreamer requires Gstreamer >= 0.10.30")
endif()
-include(${QT_USE_FILE})
-
if (CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wformat-security -Wundef -Wpointer-arith -Wcast-align -fno-common")
endif ()
diff --git a/cmake/modules/FindQtGstreamer.cmake b/cmake/modules/FindQtGstreamer.cmake
index 183c475..f1c0eff 100644
--- a/cmake/modules/FindQtGstreamer.cmake
+++ b/cmake/modules/FindQtGstreamer.cmake
@@ -22,10 +22,11 @@ else()
set(QtGstreamer_FIND_QUIETLY FALSE)
endif()
-set(_QTGSTREAMER_LINK_TO_QTCORE_REQUIRED FALSE)
+set(_QTGSTREAMER_LINK_TO_QT_REQUIRED FALSE)
if(BUILDING_QTGSTREAMER)
set(QTGSTREAMER_LIBRARY QtGstreamer)
+ set(QTGSTREAMER_UI_LIBRARY QtGstreamerUi)
set(QTGSTREAMER_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/src)
else()
# Attempt to find the generated QtGstreamerTargets.cmake in the same directory
@@ -37,28 +38,32 @@ else()
# Normally, this path is never executed. It is just provided as a fallback in case something goes wrong.
find_library(QTGSTREAMER_LIBRARY QtGstreamer
PATHS "${_QTGSTREAMER_CONFIG_DIR}/../../lib")
+ find_library(QTGSTREAMER_UI_LIBRARY QtGstreamerUi
+ PATHS "${_QTGSTREAMER_CONFIG_DIR}/../../lib")
find_path(QTGSTREAMER_INCLUDE_DIR QGst/global.h
PATHS "${_QTGSTREAMER_CONFIG_DIR}/../../include"
PATH_SUFFIXES QtGstreamer)
- set(_QTGSTREAMER_LINK_TO_QTCORE_REQUIRED TRUE)
+ set(_QTGSTREAMER_LINK_TO_QT_REQUIRED TRUE)
else()
# Targets file found. Use imported QtGstreamer target and relative include path.
# We assume that this file has been installed in $PREFIX/lib/QtGstreamer/,
# so the include path should evaluate to $PREFIX/include/QtGstreamer
include(${_QTGSTREAMER_TARGETS_FILE})
set(QTGSTREAMER_LIBRARY QtGstreamer)
+ set(QTGSTREAMER_UI_LIBRARY QtGstreamerUi)
get_filename_component(QTGSTREAMER_INCLUDE_DIR "${_QTGSTREAMER_CONFIG_DIR}/../../include/QtGstreamer" ABSOLUTE)
endif()
endif()
include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(QtGstreamer DEFAULT_MSG QTGSTREAMER_INCLUDE_DIR QTGSTREAMER_LIBRARY)
+find_package_handle_standard_args(QtGstreamer DEFAULT_MSG QTGSTREAMER_INCLUDE_DIR
+ QTGSTREAMER_LIBRARY QTGSTREAMER_UI_LIBRARY)
if(QTGSTREAMER_FOUND)
# Find dependencies, if not already found
if (NOT DEFINED QT_INCLUDE_DIR)
message(STATUS "Qt hasn't been found yet. Looking...")
- find_package(Qt4 COMPONENTS QtCore REQUIRED)
+ find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED)
endif()
if (NOT DEFINED Boost_INCLUDE_DIRS)
@@ -70,10 +75,13 @@ if(QTGSTREAMER_FOUND)
set(QTGSTREAMER_INCLUDES ${QTGSTREAMER_INCLUDE_DIR} ${QT_INCLUDE_DIR} ${Boost_INCLUDE_DIRS})
set(QTGSTREAMER_DEFINITIONS "-DQT_NO_KEYWORDS")
- if (_QTGSTREAMER_LINK_TO_QTCORE_REQUIRED)
+ if (_QTGSTREAMER_LINK_TO_QT_REQUIRED)
set(QTGSTREAMER_LIBRARIES ${QTGSTREAMER_LIBRARY} ${QT_QTCORE_LIBRARY})
+ set(QTGSTREAMER_UI_LIBRARIES ${QTGSTREAMER_UI_LIBRARY} ${QTGSTREAMER_LIBRARY}
+ ${QT_QTGUI_LIBRARY} ${QT_QTCORE_LIBRARY})
else()
set(QTGSTREAMER_LIBRARIES ${QTGSTREAMER_LIBRARY})
+ set(QTGSTREAMER_UI_LIBRARIES ${QTGSTREAMER_UI_LIBRARY})
endif()
if (CMAKE_COMPILER_IS_GNUCXX)
diff --git a/codegen/CMakeLists.txt b/codegen/CMakeLists.txt
index 4530d17..99a6c1d 100644
--- a/codegen/CMakeLists.txt
+++ b/codegen/CMakeLists.txt
@@ -1,4 +1,4 @@
-include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
+include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${QT_INCLUDE_DIR})
flex_target(analyzer analyzer.l ${CMAKE_CURRENT_BINARY_DIR}/analyzer.cpp)
bison_target(parser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp COMPILE_FLAGS "--defines")
diff --git a/elements/CMakeLists.txt b/elements/CMakeLists.txt
index 4d7e411..47d2aae 100644
--- a/elements/CMakeLists.txt
+++ b/elements/CMakeLists.txt
@@ -1,4 +1,4 @@
-include_directories(${CMAKE_CURRENT_BINARY_DIR} ${GSTREAMER_INCLUDE_DIR}
+include_directories(${CMAKE_CURRENT_BINARY_DIR} ${QT_INCLUDE_DIR} ${GSTREAMER_INCLUDE_DIR}
${GLIB2_INCLUDE_DIR} ${GSTREAMER_PLUGIN_VIDEO_INCLUDE_DIR})
add_definitions(-DGST_DISABLE_DEPRECATED)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 69b3e25..6358cdd 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -29,6 +29,10 @@ set(QtGstreamer_SRCS
${CMAKE_CURRENT_BINARY_DIR}/gen.cpp
)
+set(QtGstreamerUi_SRCS
+ QGst/Ui/videowidget.cpp
+)
+
set(INSTALLED_HEADERS
QGlib/global.h
QGlib/quark.h QGlib/Quark
@@ -66,6 +70,8 @@ set(INSTALLED_HEADERS
QGst/parse.h QGst/Parse
QGst/urihandler.h QGst/UriHandler
QGst/xoverlay.h QGst/XOverlay
+
+ QGst/Ui/videowidget.h QGst/Ui/VideoWidget
)
set(CODEGEN_HEADERS
@@ -128,8 +134,22 @@ target_link_libraries(QtGstreamer ${QT_QTCORE_LIBRARY} ${GSTREAMER_LIBRARIES}
target_link_libraries(QtGstreamer LINK_INTERFACE_LIBRARIES ${QT_QTCORE_LIBRARY})
+# Build and link QtGstreamerUi
+if(STATIC_QTGSTREAMER)
+ automoc4_add_library(QtGstreamerUi STATIC ${QtGstreamerUi_SRCS})
+else()
+ automoc4_add_library(QtGstreamerUi SHARED ${QtGstreamerUi_SRCS})
+endif()
+
+set_target_properties(QtGstreamerUi PROPERTIES SOVERSION ${QTGSTREAMER_SOVERSION}
+ VERSION ${QTGSTREAMER_VERSION})
+target_link_libraries(QtGstreamerUi ${QT_QTGUI_LIBRARY} QtGstreamer)
+target_link_libraries(QtGstreamerUi LINK_INTERFACE_LIBRARIES ${QT_QTGUI_LIBRARY} QtGstreamer)
+
+
# Install the library
install(TARGETS QtGstreamer DESTINATION ${CMAKE_INSTALL_PREFIX}/lib EXPORT QtGstreamerTargets)
+install(TARGETS QtGstreamerUi DESTINATION ${CMAKE_INSTALL_PREFIX}/lib EXPORT QtGstreamerTargets)
# Install the cmake scripts that are used to find the installed library from external projects
install(EXPORT QtGstreamerTargets DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/QtGstreamer)
diff --git a/src/QGlib/signal.h b/src/QGlib/signal.h
index 2977c7f..0df3f7d 100644
--- a/src/QGlib/signal.h
+++ b/src/QGlib/signal.h
@@ -47,6 +47,9 @@ namespace QGlib {
class SignalHandler
{
public:
+ inline SignalHandler()
+ : m_instance(NULL), m_id(0) {}
+
inline bool isValid() const { return m_instance != NULL; }
bool isConnected() const;
@@ -57,8 +60,6 @@ public:
private:
friend class Signal;
- inline SignalHandler()
- : m_instance(NULL), m_id(0) {}
inline SignalHandler(void *instance, ulong id)
: m_instance(instance), m_id(id) {}
diff --git a/src/QGst/Ui/VideoWidget b/src/QGst/Ui/VideoWidget
new file mode 100644
index 0000000..1598d38
--- /dev/null
+++ b/src/QGst/Ui/VideoWidget
@@ -0,0 +1 @@
+#include "videowidget.h"
diff --git a/src/QGst/Ui/videowidget.cpp b/src/QGst/Ui/videowidget.cpp
new file mode 100644
index 0000000..ddb3e53
--- /dev/null
+++ b/src/QGst/Ui/videowidget.cpp
@@ -0,0 +1,215 @@
+/*
+ Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@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 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 "videowidget.h"
+#include "../xoverlay.h"
+#include "../childproxy.h"
+#include "../../QGlib/signal.h"
+#include <QtCore/QDebug>
+#include <QtGui/QPainter>
+#include <QtGui/QPaintEvent>
+#include <QtGui/QResizeEvent>
+#include <QtGui/QApplication>
+
+namespace QGst {
+namespace Ui {
+
+class AbstractRenderer
+{
+public:
+ static AbstractRenderer *create(const ElementPtr & sink, QWidget *videoWidget);
+
+ virtual ~AbstractRenderer() {}
+ virtual ElementPtr videoSink() const = 0;
+};
+
+
+class XOverlayRenderer : public QObject, public AbstractRenderer
+{
+public:
+ XOverlayRenderer(const XOverlayPtr & sink, QWidget *parent)
+ : QObject(parent), m_sink(sink)
+ {
+ WId windowId = widget()->winId(); //create a new X window (if we are on X11 with alien widgets)
+ QApplication::syncX(); //inform other applications about the new window (on X11)
+ m_sink->setWindowId(static_cast<ulong>(windowId)); //### cast needs checking on non-X11 platforms
+
+ widget()->installEventFilter(this);
+ widget()->setAttribute(Qt::WA_NoSystemBackground, true);
+ widget()->setAttribute(Qt::WA_PaintOnScreen, true);
+ widget()->update();
+ }
+
+ virtual ~XOverlayRenderer()
+ {
+ m_sink->setWindowId(0);
+ widget()->removeEventFilter(this);
+ widget()->setAttribute(Qt::WA_NoSystemBackground, false);
+ widget()->setAttribute(Qt::WA_PaintOnScreen, false);
+ widget()->update();
+ }
+
+ virtual ElementPtr videoSink() const { return m_sink; }
+
+ virtual bool eventFilter(QObject *filteredObject, QEvent *event)
+ {
+ if (filteredObject == parent() && event->type() == QEvent::Paint) {
+ State currentState;
+ m_sink->getState(&currentState, NULL, 0);
+ if (currentState == StatePlaying || currentState == StatePaused) {
+ m_sink->expose();
+ } else {
+ QPainter p(widget());
+ p.fillRect(widget()->rect(), Qt::black);
+ }
+ return true;
+ } else {
+ return QObject::eventFilter(filteredObject, event);
+ }
+ }
+
+private:
+ inline QWidget *widget() { return static_cast<QWidget*>(parent()); }
+ XOverlayPtr m_sink;
+};
+
+
+class QWidgetVideoSinkRenderer : public AbstractRenderer
+{
+public:
+ QWidgetVideoSinkRenderer(const ElementPtr & sink, QWidget *parent)
+ : m_sink(sink)
+ {
+ //GValue of G_TYPE_POINTER can only be set as void* in the bindings
+ m_sink->setProperty<void*>("widget", parent);
+ }
+
+ virtual ~QWidgetVideoSinkRenderer()
+ {
+ m_sink->setProperty<void*>("widget", NULL);
+ }
+
+ virtual ElementPtr videoSink() const { return m_sink; }
+
+private:
+ ElementPtr m_sink;
+};
+
+
+class ProxyRenderer : public AbstractRenderer
+{
+public:
+ ProxyRenderer(const ChildProxyPtr & sink, QWidget *parent)
+ : m_renderer(NULL), m_parent(parent), m_sink(sink)
+ {
+ for (uint i=0; m_renderer == NULL && i<sink->childrenCount(); i++) {
+ childAdded(sink->childByIndex(i));
+ }
+
+ m_childAddedHandler = QGlib::Signal::connect(sink, "child-added",
+ this, &ProxyRenderer::childAdded);
+ m_childRemovedHandler = QGlib::Signal::connect(sink, "child-removed",
+ this, &ProxyRenderer::childRemoved);
+ }
+
+ virtual ~ProxyRenderer()
+ {
+ m_childAddedHandler.disconnect();
+ m_childRemovedHandler.disconnect();
+ }
+
+ virtual ElementPtr videoSink() const { return m_sink.dynamicCast<Element>(); }
+
+ void childAdded(const QGlib::ObjectPtr & child)
+ {
+ if (!m_renderer) {
+ ElementPtr element = child.dynamicCast<Element>();
+ if (element) {
+ m_renderer = AbstractRenderer::create(element, m_parent);
+ }
+ }
+ }
+
+ void childRemoved(const QGlib::ObjectPtr & child)
+ {
+ if (m_renderer && m_renderer->videoSink() == child) {
+ delete m_renderer;
+ m_renderer = NULL;
+ }
+ }
+
+private:
+ AbstractRenderer *m_renderer;
+ QWidget *m_parent;
+ ChildProxyPtr m_sink;
+ QGlib::SignalHandler m_childAddedHandler;
+ QGlib::SignalHandler m_childRemovedHandler;
+};
+
+
+AbstractRenderer *AbstractRenderer::create(const ElementPtr & sink, QWidget *videoWidget)
+{
+#if !defined(Q_WS_QWS)
+ XOverlayPtr overlay = sink.dynamicCast<XOverlay>();
+ if (overlay) {
+ return new XOverlayRenderer(overlay, videoWidget);
+ }
+#endif
+
+ if (QGlib::Type::fromInstance(sink).name() == QLatin1String("GstQWidgetVideoSink")) {
+ return new QWidgetVideoSinkRenderer(sink, videoWidget);
+ }
+
+ ChildProxyPtr childProxy = sink.dynamicCast<ChildProxy>();
+ if (childProxy) {
+ return new ProxyRenderer(childProxy, videoWidget);
+ }
+
+ return NULL;
+}
+
+
+VideoWidget::VideoWidget(QWidget *parent, Qt::WindowFlags f)
+ : QWidget(parent, f), d(NULL)
+{
+}
+
+VideoWidget::~VideoWidget()
+{
+ delete d;
+}
+
+ElementPtr VideoWidget::videoSink() const
+{
+ return d ? d->videoSink() : ElementPtr();
+}
+
+void VideoWidget::setVideoSink(const ElementPtr & sink)
+{
+ delete d;
+ d = NULL;
+
+ if (sink) {
+ d = AbstractRenderer::create(sink, this);
+
+ if (!d) {
+ qCritical() << "QGst::Ui::VideoWidget: Could not construct a renderer for the specified element";
+ }
+ }
+}
+
+} //namespace Ui
+} //namespace QGst
diff --git a/src/QGst/Ui/videowidget.h b/src/QGst/Ui/videowidget.h
new file mode 100644
index 0000000..63f36b1
--- /dev/null
+++ b/src/QGst/Ui/videowidget.h
@@ -0,0 +1,63 @@
+/*
+ Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@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 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 QGST_UI_VIDEOWIDGET_H
+#define QGST_UI_VIDEOWIDGET_H
+
+#include "../element.h"
+#include <QtGui/QWidget>
+
+namespace QGst {
+namespace Ui {
+
+class AbstractRenderer;
+
+/*! \headerfile videowidget.h <QGst/Ui/VideoWidget>
+ * \brief A generic video widget that can embed a video sink
+ *
+ * This widget allows you to embed a video sink on a Qt user interface.
+ * It supports a wide range of video sinks, including all the sinks that
+ * implement the XOverlay interface, the "qwidgetvideosink" and autoplug
+ * video sinks, such as "autovideosink" and "gconfvideosink". Because the
+ * autoplug sinks are actualy bins, this widget can also accept any kind
+ * of bin (to be precise, anything that implements the ChildProxy interface).
+ * However, it is not recommended to use it with bins, unless you are
+ * completely sure that there can be no child bins and there can be only
+ * one video sink element in this bin.
+ */
+class VideoWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ VideoWidget(QWidget *parent = 0, Qt::WindowFlags f = 0);
+ virtual ~VideoWidget();
+
+ /*! Returns the video sink element that was set using setVideoSink(),
+ * or a null ElementPtr if no sink has been set. */
+ ElementPtr videoSink() const;
+
+ /*! Sets the video sink element that is going to be embedded. You can safely
+ * pass a null ElementPtr here to remove the previously embedded sink. */
+ void setVideoSink(const ElementPtr & sink);
+
+private:
+ AbstractRenderer *d;
+};
+
+} //namespace Ui
+} //namespace QGst
+
+#endif // QGST_UI_VIDEOWIDGET_H
diff --git a/src/main.dox b/src/main.dox
index 3ec4220..9ea66b0 100644
--- a/src/main.dox
+++ b/src/main.dox
@@ -20,6 +20,13 @@
* This namespace provides wrapper classes for GStreamer objects.
*/
+/*! \namespace QGst::Ui
+ * \brief Helper classes for better integration of GStreamer in graphical Qt applications
+ *
+ * This namespace provides helper classes for better integration of GStreamer
+ * in graphical Qt applications.
+ */
+
/*! \example echo/main.cpp
* This is a trivial example which echoes the microphone input to the output
*/
diff --git a/tests/manual/CMakeLists.txt b/tests/manual/CMakeLists.txt
index 169bc96..9104dcf 100644
--- a/tests/manual/CMakeLists.txt
+++ b/tests/manual/CMakeLists.txt
@@ -5,3 +5,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${QTGSTREAMER_FLAGS}")
qt4_wrap_ui(QWIDGETVIDEOSINKTEST_UI qwidgetvideosinktest.ui)
automoc4_add_executable(qwidgetvideosinktest qwidgetvideosinktest.cpp ${QWIDGETVIDEOSINKTEST_UI})
target_link_libraries(qwidgetvideosinktest ${QT_QTGUI_LIBRARIES} ${QTGSTREAMER_LIBRARIES})
+
+
+qt4_wrap_ui(VIDEOWIDGETTEST_UI videowidgettest.ui)
+automoc4_add_executable(videowidgettest videowidgettest.cpp ${VIDEOWIDGETTEST_UI})
+target_link_libraries(videowidgettest ${QTGSTREAMER_UI_LIBRARIES})
diff --git a/tests/manual/videowidgettest.cpp b/tests/manual/videowidgettest.cpp
new file mode 100644
index 0000000..747e1da
--- /dev/null
+++ b/tests/manual/videowidgettest.cpp
@@ -0,0 +1,110 @@
+/*
+ Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@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 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 "ui_videowidgettest.h"
+#include <QGst/Pipeline>
+#include <QGst/ElementFactory>
+#include <QtGui/QApplication>
+#include <QtGui/QMessageBox>
+#include <QtGui/QButtonGroup>
+
+class VideoWidgetTest : public QWidget
+{
+ Q_OBJECT
+public:
+ VideoWidgetTest(QWidget* parent = 0, Qt::WindowFlags f = 0);
+
+private Q_SLOTS:
+ void onButtonClicked(int id);
+ void on_forceAspectRatioCheckBox_toggled(bool on);
+
+private:
+ Ui::VideoWidgetTest m_ui;
+ QGst::PipelinePtr m_pipeline;
+ QGst::ElementPtr m_src;
+ QGst::ElementPtr m_sink;
+};
+
+VideoWidgetTest::VideoWidgetTest(QWidget *parent, Qt::WindowFlags f)
+ : QWidget(parent, f)
+{
+ m_ui.setupUi(this);
+
+ QButtonGroup *group = new QButtonGroup(this);
+ group->addButton(m_ui.playingButton, QGst::StatePlaying);
+ group->addButton(m_ui.pausedButton, QGst::StatePaused);
+ group->addButton(m_ui.readyButton, QGst::StateReady);
+ group->addButton(m_ui.nullButton, QGst::StateNull);
+ connect(group, SIGNAL(buttonClicked(int)), SLOT(onButtonClicked(int)));
+
+ m_pipeline = QGst::Pipeline::create();
+ m_src = QGst::ElementFactory::make("videotestsrc");
+
+ if (!m_src) {
+ throw std::runtime_error("Unable to create a videotestsrc");
+ }
+
+ m_pipeline->add(m_src);
+}
+
+void VideoWidgetTest::onButtonClicked(int id)
+{
+ QGst::State currentState;
+ m_pipeline->getState(&currentState, NULL, 0);
+
+ if (currentState == QGst::StateNull) {
+ if (m_sink) {
+ m_ui.videoWidget->setVideoSink(QGst::ElementPtr());
+ m_pipeline->remove(m_sink);
+ }
+
+ m_sink = QGst::ElementFactory::make(m_ui.elementNameEdit->text().toUtf8());
+
+ if (!m_sink) {
+ QMessageBox::critical(this, "Error", "Could not create the specified sink element");
+ } else {
+ m_pipeline->add(m_sink);
+ m_src->link(m_sink);
+ m_ui.videoWidget->setVideoSink(m_sink);
+ }
+ }
+
+ if (m_sink) {
+ QGst::State state = static_cast<QGst::State>(id);
+ m_pipeline->setState(state);
+ }
+}
+
+void VideoWidgetTest::on_forceAspectRatioCheckBox_toggled(bool on)
+{
+ if (m_sink) {
+ m_sink->setProperty("force-aspect-ratio", on);
+ m_ui.videoWidget->update();
+ }
+}
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ QGst::init(&argc, &argv);
+
+ VideoWidgetTest test;
+ test.show();
+
+ return app.exec();
+}
+
+#include "videowidgettest.moc"
diff --git a/tests/manual/videowidgettest.ui b/tests/manual/videowidgettest.ui
new file mode 100644
index 0000000..033d7c3
--- /dev/null
+++ b/tests/manual/videowidgettest.ui
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>VideoWidgetTest</class>
+ <widget class="QWidget" name="VideoWidgetTest">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>544</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>VideoWidgetTest</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Set pipeline state</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QPushButton" name="playingButton">
+ <property name="text">
+ <string>PLAYING</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pausedButton">
+ <property name="text">
+ <string>PAUSED</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="readyButton">
+ <property name="text">
+ <string>READY</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="nullButton">
+ <property name="text">
+ <string>NULL</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSplitter" name="splitter">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <widget class="QWidget" name="">
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Element name</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLineEdit" name="elementNameEdit">
+ <property name="text">
+ <string>xvimagesink</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Misc</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QCheckBox" name="forceAspectRatioCheckBox">
+ <property name="text">
+ <string>force-aspect-ratio</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QGst::Ui::VideoWidget" name="videoWidget" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QGst::Ui::VideoWidget</class>
+ <extends>QWidget</extends>
+ <header location="global">QGst/Ui/VideoWidget</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>nullButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>elementNameEdit</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>467</x>
+ <y>40</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>103</x>
+ <y>129</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>