diff options
Diffstat (limited to 'src/3rdparty/phonon/gstreamer/x11renderer.cpp')
-rw-r--r-- | src/3rdparty/phonon/gstreamer/x11renderer.cpp | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/src/3rdparty/phonon/gstreamer/x11renderer.cpp b/src/3rdparty/phonon/gstreamer/x11renderer.cpp new file mode 100644 index 0000000..73877a8 --- /dev/null +++ b/src/3rdparty/phonon/gstreamer/x11renderer.cpp @@ -0,0 +1,194 @@ +/* This file is part of the KDE project. + + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + + 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 or 3 of the License. + + This library 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 library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "videowidget.h" +#include "x11renderer.h" + +#ifndef Q_WS_QWS + +#include <QtGui/QPalette> +#include <QtGui/QApplication> +#include <QtGui/QPainter> +#include <X11/Xlib.h> +#include <gst/gst.h> +#include <gst/interfaces/xoverlay.h> +#include <gst/interfaces/propertyprobe.h> +#include "common.h" +#include "mediaobject.h" +#include "message.h" + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ +namespace Gstreamer +{ + +class OverlayWidget : public QWidget +{ +public: + OverlayWidget(VideoWidget *videoWidget, X11Renderer *renderer) : + QWidget(videoWidget), + m_videoWidget(videoWidget), + m_renderer(renderer) { } + void paintEvent(QPaintEvent *) { + Phonon::State state = m_videoWidget->root() ? m_videoWidget->root()->state() : Phonon::LoadingState; + if (state == Phonon::PlayingState || state == Phonon::PausedState) { + m_renderer->windowExposed(); + } else { + QPainter painter(this); + painter.fillRect(m_videoWidget->rect(), m_videoWidget->palette().background()); + } + } +private: + VideoWidget *m_videoWidget; + X11Renderer *m_renderer; +}; + +X11Renderer::X11Renderer(VideoWidget *videoWidget) + : AbstractRenderer(videoWidget) +{ + m_renderWidget = new OverlayWidget(videoWidget, this); + videoWidget->backend()->logMessage("Creating X11 overlay renderer"); + QPalette palette; + palette.setColor(QPalette::Background, Qt::black); + m_videoWidget->setPalette(palette); + m_videoWidget->setAutoFillBackground(true); + m_renderWidget->setMouseTracking(true); + m_videoSink = createVideoSink(); + aspectRatioChanged(videoWidget->aspectRatio()); + setOverlay(); +} + +X11Renderer::~X11Renderer() +{ + m_renderWidget->setAttribute(Qt::WA_PaintOnScreen, false); + m_renderWidget->setAttribute(Qt::WA_NoSystemBackground, false); + delete m_renderWidget; +} + +GstElement* X11Renderer::createVideoSink() +{ + GstElement *videoSink = gst_element_factory_make ("xvimagesink", NULL); + if (videoSink) { + // Check if the xv sink is usable + if (gst_element_set_state(videoSink, GST_STATE_READY) != GST_STATE_CHANGE_SUCCESS) { + gst_object_unref(GST_OBJECT(videoSink)); + videoSink = 0; + } else { + // Note that this should not really be neccessary as these are + // default values, though under certain conditions values are retained + // even between application instances. (reproducible on 0.10.16/Gutsy) + g_object_set(G_OBJECT(videoSink), "brightness", 0, (const char*)NULL); + g_object_set(G_OBJECT(videoSink), "contrast", 0, (const char*)NULL); + g_object_set(G_OBJECT(videoSink), "hue", 0, (const char*)NULL); + g_object_set(G_OBJECT(videoSink), "saturation", 0, (const char*)NULL); + } + } + + if (!videoSink) + videoSink = gst_element_factory_make ("ximagesink", NULL); + + gst_object_ref (GST_OBJECT (videoSink)); //Take ownership + gst_object_sink (GST_OBJECT (videoSink)); + + return videoSink; +} + +void X11Renderer::handleMediaNodeEvent(const MediaNodeEvent *event) +{ + switch (event->type()) { + case MediaNodeEvent::SourceChanged: + setOverlay(); // We need to do this whenever the pipeline is reset + break; // otherwise the videosink will open in its own window + default: + break; + } +} + + +void X11Renderer::aspectRatioChanged(Phonon::VideoWidget::AspectRatio) +{ + if (m_renderWidget) { + m_renderWidget->setGeometry(m_videoWidget->calculateDrawFrameRect()); + } +} + +void X11Renderer::scaleModeChanged(Phonon::VideoWidget::ScaleMode) +{ + if (m_renderWidget) { + m_renderWidget->setGeometry(m_videoWidget->calculateDrawFrameRect()); + } +} + +void X11Renderer::movieSizeChanged(const QSize &movieSize) +{ + Q_UNUSED(movieSize); + if (m_renderWidget) { + m_renderWidget->setGeometry(m_videoWidget->calculateDrawFrameRect()); + } +} + +bool X11Renderer::eventFilter(QEvent *e) +{ + if (e->type() == QEvent::Show) { + // Setting these values ensures smooth resizing since it + // will prevent the system from clearing the background + m_renderWidget->setAttribute(Qt::WA_NoSystemBackground, true); + m_renderWidget->setAttribute(Qt::WA_PaintOnScreen, true); + setOverlay(); + } else if (e->type() == QEvent::Resize) { + // This is a workaround for missing background repaints + // when reducing window size + m_renderWidget->setGeometry(m_videoWidget->calculateDrawFrameRect()); + windowExposed(); + } + return false; +} + +void X11Renderer::handlePaint(QPaintEvent *) +{ + QPainter painter(m_videoWidget); + painter.fillRect(m_videoWidget->rect(), m_videoWidget->palette().background()); +} + +void X11Renderer::setOverlay() +{ + if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { + WId windowId = m_renderWidget->winId(); + // Even if we have created a winId at this point, other X applications + // need to be aware of it. + QApplication::syncX(); + gst_x_overlay_set_xwindow_id ( GST_X_OVERLAY(m_videoSink) , windowId ); + } + windowExposed(); + m_overlaySet = true; +} + +void X11Renderer::windowExposed() +{ + QApplication::syncX(); + if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) + gst_x_overlay_expose(GST_X_OVERLAY(m_videoSink)); +} + +} +} //namespace Phonon::Gstreamer + +QT_END_NAMESPACE + +#endif // Q_WS_QWS |