diff options
-rw-r--r-- | CMakeLists.txt | 4 | ||||
-rw-r--r-- | cmake/modules/FindQtGstreamer.cmake | 18 | ||||
-rw-r--r-- | codegen/CMakeLists.txt | 2 | ||||
-rw-r--r-- | elements/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/CMakeLists.txt | 20 | ||||
-rw-r--r-- | src/QGlib/signal.h | 5 | ||||
-rw-r--r-- | src/QGst/Ui/VideoWidget | 1 | ||||
-rw-r--r-- | src/QGst/Ui/videowidget.cpp | 215 | ||||
-rw-r--r-- | src/QGst/Ui/videowidget.h | 63 | ||||
-rw-r--r-- | src/main.dox | 7 | ||||
-rw-r--r-- | tests/manual/CMakeLists.txt | 5 | ||||
-rw-r--r-- | tests/manual/videowidgettest.cpp | 110 | ||||
-rw-r--r-- | tests/manual/videowidgettest.ui | 170 |
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(¤tState, 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(¤tState, 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> |