/* 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 <QtGui/QPainter>+ −
#include <QtGui/QPaintEvent>+ −
#include <QtCore/QTimer>+ −
#include <QtCore/QSettings>+ −
+ −
#include "mediaobject.h"+ −
+ −
#ifndef Q_OS_WINCE+ −
#include "videorenderer_evr.h"+ −
#include "videorenderer_vmr9.h"+ −
#else+ −
#include "videorenderer_default.h"+ −
#endif+ −
#include "videorenderer_soft.h"+ −
+ −
QT_BEGIN_NAMESPACE+ −
+ −
#ifndef QT_NO_PHONON_VIDEO+ −
+ −
namespace Phonon+ −
{+ −
namespace DS9+ −
{+ −
//class used internally to return the widget where the video is shown on+ −
class VideoWindow : public QWidget+ −
{+ −
public:+ −
explicit VideoWindow(QWidget *parent, VideoWidget *vw)+ −
: QWidget(parent), m_node(vw), m_currentRenderer(0)+ −
{+ −
//default background color+ −
setPalette(QPalette(Qt::black)); + −
setAttribute(Qt::WA_OpaquePaintEvent, true);+ −
setAttribute(Qt::WA_NoSystemBackground, true);+ −
setAttribute(Qt::WA_PaintOnScreen, true);+ −
setAutoFillBackground(false);+ −
}+ −
+ −
QPaintEngine* paintEngine() const+ −
{+ −
return 0;+ −
}+ −
+ −
bool isEmbedded() const+ −
{+ −
#if QT_VERSION >= 0x040400+ −
return window()->testAttribute(Qt::WA_DontShowOnScreen);+ −
#else+ −
return false;+ −
#endif+ −
}+ −
+ −
bool needsSoftRendering() const+ −
{+ −
QPaintDevice *dev = QPainter::redirected(this, 0);+ −
return (dev && dev != this);+ −
}+ −
+ −
void resizeEvent(QResizeEvent *e)+ −
{+ −
m_node->updateVideoSize();+ −
QWidget::resizeEvent(e);+ −
}+ −
+ −
AbstractVideoRenderer *currentRenderer() const+ −
{+ −
return m_currentRenderer;+ −
}+ −
+ −
void setCurrentRenderer(AbstractVideoRenderer *renderer)+ −
{+ −
m_currentRenderer = renderer;+ −
//we disallow repaint on that widget for just a fraction of second+ −
//this allows better transition between videos+ −
setUpdatesEnabled(false);+ −
m_flickerFreeTimer.start(20, this);+ −
}+ −
+ −
void timerEvent(QTimerEvent *e)+ −
{+ −
if (e->timerId() == m_flickerFreeTimer.timerId()) {+ −
m_flickerFreeTimer.stop();+ −
setUpdatesEnabled(true);+ −
}+ −
QWidget::timerEvent(e);+ −
}+ −
+ −
QSize sizeHint() const+ −
{+ −
return m_currentRenderer->sizeHint().expandedTo(QWidget::sizeHint());+ −
}+ −
+ −
void changeEvent(QEvent *e)+ −
{+ −
checkCurrentRenderingMode();+ −
QWidget::changeEvent(e);+ −
}+ −
+ −
void setVisible(bool visible)+ −
{+ −
checkCurrentRenderingMode();+ −
QWidget::setVisible(visible);+ −
}+ −
+ −
void paintEvent(QPaintEvent *e)+ −
{+ −
if (!updatesEnabled())+ −
return; //this avoids repaint from native events+ −
checkCurrentRenderingMode();+ −
m_currentRenderer->repaintCurrentFrame(this, e->rect());+ −
}+ −
+ −
//this code manages the activation/deactivation of the screensaver+ −
/*bool event(QEvent *e)+ −
{+ −
if (e->type() == QEvent::Resize) {+ −
//we disable the screensaver if the video is in fullscreen mode+ −
disableScreenSaver(window()->windowState() & Qt::WindowFullScreen);+ −
}+ −
return QWidget::event(e);+ −
}*/+ −
+ −
private:+ −
//for fullscreen mode+ −
void disableScreenSaver(bool b)+ −
{+ −
const QLatin1String screenSaverActive("ScreenSaveActive");+ −
QSettings settings( QLatin1String("HKEY_CURRENT_USER\\Control Panel\\Desktop"), QSettings::NativeFormat);+ −
if (b) {+ −
if (m_restoreScreenSaverActive.isNull()) {+ −
//we store the value to be able to restore it later+ −
m_restoreScreenSaverActive = settings.value(screenSaverActive);+ −
settings.setValue(screenSaverActive, QString::number(!b));+ −
}+ −
} else if (!m_restoreScreenSaverActive.isNull()) {+ −
//we restore the previous value+ −
settings.setValue(screenSaverActive, m_restoreScreenSaverActive);+ −
}+ −
}+ −
+ −
void checkCurrentRenderingMode()+ −
{+ −
if (!m_currentRenderer)+ −
return;+ −
+ −
if (m_currentRenderer->isNative()) {+ −
if (isEmbedded()) {+ −
//we need to switch to software renderer+ −
m_currentRenderer = m_node->switchRendering(m_currentRenderer);+ −
setAttribute(Qt::WA_PaintOnScreen, false);+ −
} else if (needsSoftRendering()) {+ −
m_node->performSoftRendering(m_currentRenderer->snapshot());+ −
}+ −
} else if (!isEmbedded()) {+ −
m_currentRenderer = m_node->switchRendering(m_currentRenderer);+ −
setAttribute(Qt::WA_PaintOnScreen, false);+ −
}+ −
}+ −
+ −
VideoWidget *m_node;+ −
AbstractVideoRenderer *m_currentRenderer;+ −
QVariant m_restoreScreenSaverActive;+ −
QBasicTimer m_flickerFreeTimer;+ −
};+ −
+ −
VideoWidget::VideoWidget(QWidget *parent)+ −
: BackendNode(parent), m_aspectRatio(Phonon::VideoWidget::AspectRatioAuto),+ −
m_scaleMode(Phonon::VideoWidget::FitInView),+ −
m_brightness(0.), m_contrast(0.), m_hue(0.), m_saturation(0.), m_noNativeRendererSupported(false)+ −
+ −
{+ −
//initialisation of the widget+ −
m_widget = new VideoWindow(parent, this);+ −
+ −
//initialization of the renderers+ −
qMemSet(m_renderers, 0, sizeof(m_renderers));+ −
+ −
for(int i = 0; i< FILTER_COUNT ;++i) {+ −
//This might return a non native (ie Qt) renderer in case native is not supported+ −
AbstractVideoRenderer *renderer = getRenderer(i, Native, true);+ −
m_filters[i] = renderer->getFilter();+ −
}+ −
+ −
//by default, we take the first VideoWindow object+ −
setCurrentGraph(0);+ −
}+ −
+ −
VideoWidget::~VideoWidget()+ −
{+ −
for (int i = 0; i < 4; ++i) {+ −
delete m_renderers[i];+ −
}+ −
}+ −
+ −
void VideoWidget::notifyVideoLoaded()+ −
{+ −
updateVideoSize();+ −
m_widget->updateGeometry();+ −
}+ −
+ −
AbstractVideoRenderer *VideoWidget::switchRendering(AbstractVideoRenderer *current)+ −
{+ −
const bool toNative = !current->isNative();+ −
if (toNative && m_noNativeRendererSupported)+ −
return current; //no switch here+ −
+ −
if (!mediaObject())+ −
return current;+ −
+ −
//firt we delete the renderer+ −
//initialization of the widgets+ −
for(int i = 0; i < FILTER_COUNT; ++i) {+ −
Filter oldFilter = m_filters[i];+ −
+ −
//Let's create a software renderer+ −
AbstractVideoRenderer *renderer = getRenderer(i, toNative ? Native : NonNative, true);+ −
+ −
if (m_mediaObject) {+ −
m_mediaObject->switchFilters(i, oldFilter, renderer->getFilter());+ −
}+ −
+ −
m_filters[i] = renderer->getFilter();+ −
}+ −
+ −
return getRenderer(mediaObject()->currentGraph()->index(), toNative ? Native: NonNative);+ −
}+ −
+ −
void VideoWidget::performSoftRendering(const QImage ¤tImage)+ −
{+ −
const int graphIndex = mediaObject()->currentGraph()->index();+ −
VideoRendererSoft *r = static_cast<VideoRendererSoft*>(getRenderer(graphIndex, NonNative, true /*autocreation*/));+ −
r->setSnapshot(currentImage);+ −
r->notifyResize(m_widget->size(), m_aspectRatio, m_scaleMode);+ −
r->repaintCurrentFrame(m_widget, m_widget->rect());+ −
+ −
}+ −
+ −
void VideoWidget::setCurrentGraph(int index)+ −
{+ −
for(int i = 0; i < 2; ++i) {+ −
if (AbstractVideoRenderer *renderer = getRenderer(i, Native))+ −
renderer->setActive(index == i);+ −
}+ −
+ −
//be sure to update all the things that needs an update+ −
applyMixerSettings();+ −
updateVideoSize();+ −
+ −
AbstractVideoRenderer *r = m_widget->currentRenderer();+ −
+ −
//we determine dynamically if it is native or non native+ −
r = getRenderer(index, !r || r->isNative() ? Native : NonNative);+ −
if (!r)+ −
r = getRenderer(index, NonNative);+ −
m_widget->setCurrentRenderer(r);+ −
}+ −
+ −
+ −
Phonon::VideoWidget::AspectRatio VideoWidget::aspectRatio() const+ −
{+ −
return m_aspectRatio;+ −
}+ −
+ −
void VideoWidget::setAspectRatio(Phonon::VideoWidget::AspectRatio aspectRatio)+ −
{+ −
m_aspectRatio = aspectRatio;+ −
updateVideoSize();+ −
m_widget->update();+ −
}+ −
+ −
Phonon::VideoWidget::ScaleMode VideoWidget::scaleMode() const+ −
{+ −
return m_scaleMode;+ −
}+ −
+ −
+ −
QWidget *VideoWidget::widget()+ −
{+ −
return m_widget;+ −
}+ −
+ −
+ −
void VideoWidget::setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode)+ −
{+ −
m_scaleMode = scaleMode;+ −
updateVideoSize();+ −
m_widget->update();+ −
}+ −
+ −
void VideoWidget::setBrightness(qreal b)+ −
{+ −
m_brightness = b;+ −
applyMixerSettings();+ −
}+ −
+ −
void VideoWidget::setContrast(qreal c)+ −
{+ −
m_contrast = c;+ −
applyMixerSettings();+ −
}+ −
+ −
void VideoWidget::setHue(qreal h)+ −
{+ −
m_hue = h;+ −
applyMixerSettings();+ −
}+ −
+ −
void VideoWidget::setSaturation(qreal s)+ −
{+ −
m_saturation = s;+ −
applyMixerSettings();+ −
}+ −
+ −
qreal VideoWidget::brightness() const+ −
{+ −
return m_brightness;+ −
}+ −
+ −
+ −
qreal VideoWidget::contrast() const+ −
{+ −
return m_contrast;+ −
}+ −
+ −
qreal VideoWidget::hue() const+ −
{+ −
return m_hue;+ −
}+ −
+ −
qreal VideoWidget::saturation() const+ −
{+ −
return m_saturation;+ −
}+ −
+ −
+ −
AbstractVideoRenderer *VideoWidget::getRenderer(int graphIndex, RendererType type, bool autoCreate)+ −
{+ −
int index = graphIndex * 2 + type;+ −
if (m_renderers[index] == 0 && autoCreate) {+ −
AbstractVideoRenderer *renderer = 0;+ −
if (type == Native) {+ −
#ifndef Q_OS_WINCE+ −
renderer = new VideoRendererEVR(m_widget);+ −
if (renderer->getFilter() == 0) {+ −
delete renderer;+ −
//EVR not present, let's try VMR+ −
renderer = new VideoRendererVMR9(m_widget);+ −
if (renderer->getFilter() == 0) {+ −
//instanciating the renderer might fail+ −
m_noNativeRendererSupported = true;+ −
delete renderer;+ −
renderer = 0;+ −
}+ −
}+ −
#else+ −
renderer = new VideoRendererDefault(m_widget);+ −
if (renderer->getFilter() == 0) {+ −
//instanciating the renderer might fail+ −
m_noNativeRendererSupported = true;+ −
delete renderer;+ −
renderer = 0;+ −
}+ −
#endif+ −
}+ −
+ −
if (renderer == 0) {+ −
type = NonNative;+ −
index = graphIndex * 2 + type;+ −
if (m_renderers[index] == 0)+ −
renderer = new VideoRendererSoft(m_widget); //this always succeeds+ −
else+ −
renderer = m_renderers[index];+ −
}+ −
+ −
m_renderers[index] = renderer;+ −
+ −
//be sure to update all the things that needs an update+ −
applyMixerSettings();+ −
updateVideoSize();+ −
+ −
}+ −
return m_renderers[index];+ −
}+ −
+ −
//this must be called whe nthe node is actually connected+ −
void VideoWidget::applyMixerSettings() const+ −
{+ −
for (int i = 0; i < 4; ++i) {+ −
if (AbstractVideoRenderer *renderer = m_renderers[i])+ −
renderer->applyMixerSettings(m_brightness, m_contrast, m_hue, m_saturation);+ −
}+ −
}+ −
+ −
void VideoWidget::connected(BackendNode *, const InputPin&)+ −
{+ −
//in case of a connection, we simply reapply the mixer settings+ −
applyMixerSettings();+ −
updateVideoSize();+ −
}+ −
+ −
void VideoWidget::updateVideoSize() const+ −
{+ −
for (int i = 0; i < 4; ++i) {+ −
if (AbstractVideoRenderer *renderer = m_renderers[i])+ −
renderer->notifyResize(m_widget->size(), m_aspectRatio, m_scaleMode);+ −
}+ −
}+ −
+ −
+ −
+ −
}+ −
}+ −
+ −
#endif //QT_NO_PHONON_VIDEO+ −
+ −
QT_END_NAMESPACE+ −
+ −
#include "moc_videowidget.cpp"+ −