source: trunk/src/3rdparty/phonon/ds9/videowidget.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 14.0 KB
Line 
1/* This file is part of the KDE project.
2
3Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4
5This library is free software: you can redistribute it and/or modify
6it under the terms of the GNU Lesser General Public License as published by
7the Free Software Foundation, either version 2.1 or 3 of the License.
8
9This library is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU Lesser General Public License for more details.
13
14You should have received a copy of the GNU Lesser General Public License
15along with this library. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include "videowidget.h"
19
20#include <QtGui/QPainter>
21#include <QtGui/QPaintEvent>
22#include <QtCore/QTimer>
23#include <QtCore/QSettings>
24
25#include "mediaobject.h"
26
27#ifndef Q_OS_WINCE
28#include "videorenderer_evr.h"
29#include "videorenderer_vmr9.h"
30#else
31#include "videorenderer_default.h"
32#endif
33#include "videorenderer_soft.h"
34
35QT_BEGIN_NAMESPACE
36
37#ifndef QT_NO_PHONON_VIDEO
38
39namespace Phonon
40{
41 namespace DS9
42 {
43 //class used internally to return the widget where the video is shown on
44 class VideoWindow : public QWidget
45 {
46 public:
47 explicit VideoWindow(QWidget *parent, VideoWidget *vw)
48 : QWidget(parent), m_node(vw), m_currentRenderer(0)
49 {
50 //default background color
51 setPalette(QPalette(Qt::black));
52 setAttribute(Qt::WA_OpaquePaintEvent, true);
53 setAttribute(Qt::WA_NoSystemBackground, true);
54 setAttribute(Qt::WA_PaintOnScreen, true);
55 setAutoFillBackground(false);
56 }
57
58 QPaintEngine* paintEngine() const
59 {
60 return 0;
61 }
62
63 bool isEmbedded() const
64 {
65#if QT_VERSION >= 0x040400
66 return window()->testAttribute(Qt::WA_DontShowOnScreen);
67#else
68 return false;
69#endif
70 }
71
72 bool needsSoftRendering() const
73 {
74 QPaintDevice *dev = QPainter::redirected(this, 0);
75 return (dev && dev != this);
76 }
77
78 void resizeEvent(QResizeEvent *e)
79 {
80 m_node->updateVideoSize();
81 QWidget::resizeEvent(e);
82 }
83
84 AbstractVideoRenderer *currentRenderer() const
85 {
86 return m_currentRenderer;
87 }
88
89 void setCurrentRenderer(AbstractVideoRenderer *renderer)
90 {
91 m_currentRenderer = renderer;
92 //we disallow repaint on that widget for just a fraction of second
93 //this allows better transition between videos
94 setUpdatesEnabled(false);
95 m_flickerFreeTimer.start(20, this);
96 }
97
98 void timerEvent(QTimerEvent *e)
99 {
100 if (e->timerId() == m_flickerFreeTimer.timerId()) {
101 m_flickerFreeTimer.stop();
102 setUpdatesEnabled(true);
103 }
104 QWidget::timerEvent(e);
105 }
106
107 QSize sizeHint() const
108 {
109 return m_currentRenderer->sizeHint().expandedTo(QWidget::sizeHint());
110 }
111
112 void changeEvent(QEvent *e)
113 {
114 checkCurrentRenderingMode();
115 QWidget::changeEvent(e);
116 }
117
118 void setVisible(bool visible)
119 {
120 checkCurrentRenderingMode();
121 QWidget::setVisible(visible);
122 }
123
124 void paintEvent(QPaintEvent *e)
125 {
126 if (!updatesEnabled())
127 return; //this avoids repaint from native events
128 checkCurrentRenderingMode();
129 m_currentRenderer->repaintCurrentFrame(this, e->rect());
130 }
131
132 //this code manages the activation/deactivation of the screensaver
133 /*bool event(QEvent *e)
134 {
135 if (e->type() == QEvent::Resize) {
136 //we disable the screensaver if the video is in fullscreen mode
137 disableScreenSaver(window()->windowState() & Qt::WindowFullScreen);
138 }
139 return QWidget::event(e);
140 }*/
141
142 private:
143 //for fullscreen mode
144 void disableScreenSaver(bool b)
145 {
146 const QLatin1String screenSaverActive("ScreenSaveActive");
147 QSettings settings( QLatin1String("HKEY_CURRENT_USER\\Control Panel\\Desktop"), QSettings::NativeFormat);
148 if (b) {
149 if (m_restoreScreenSaverActive.isNull()) {
150 //we store the value to be able to restore it later
151 m_restoreScreenSaverActive = settings.value(screenSaverActive);
152 settings.setValue(screenSaverActive, QString::number(!b));
153 }
154 } else if (!m_restoreScreenSaverActive.isNull()) {
155 //we restore the previous value
156 settings.setValue(screenSaverActive, m_restoreScreenSaverActive);
157 }
158 }
159
160 void checkCurrentRenderingMode()
161 {
162 if (!m_currentRenderer)
163 return;
164
165 if (m_currentRenderer->isNative()) {
166 if (isEmbedded()) {
167 //we need to switch to software renderer
168 m_currentRenderer = m_node->switchRendering(m_currentRenderer);
169 setAttribute(Qt::WA_PaintOnScreen, false);
170 } else if (needsSoftRendering()) {
171 m_node->performSoftRendering(m_currentRenderer->snapshot());
172 }
173 } else if (!isEmbedded()) {
174 m_currentRenderer = m_node->switchRendering(m_currentRenderer);
175 setAttribute(Qt::WA_PaintOnScreen, false);
176 }
177 }
178
179 VideoWidget *m_node;
180 AbstractVideoRenderer *m_currentRenderer;
181 QVariant m_restoreScreenSaverActive;
182 QBasicTimer m_flickerFreeTimer;
183 };
184
185 VideoWidget::VideoWidget(QWidget *parent)
186 : BackendNode(parent), m_aspectRatio(Phonon::VideoWidget::AspectRatioAuto),
187 m_scaleMode(Phonon::VideoWidget::FitInView),
188 m_brightness(0.), m_contrast(0.), m_hue(0.), m_saturation(0.), m_noNativeRendererSupported(false)
189
190 {
191 //initialisation of the widget
192 m_widget = new VideoWindow(parent, this);
193
194 //initialization of the renderers
195 qMemSet(m_renderers, 0, sizeof(m_renderers));
196
197 for(int i = 0; i< FILTER_COUNT ;++i) {
198 //This might return a non native (ie Qt) renderer in case native is not supported
199 AbstractVideoRenderer *renderer = getRenderer(i, Native, true);
200 m_filters[i] = renderer->getFilter();
201 }
202
203 //by default, we take the first VideoWindow object
204 setCurrentGraph(0);
205 }
206
207 VideoWidget::~VideoWidget()
208 {
209 for (int i = 0; i < 4; ++i) {
210 delete m_renderers[i];
211 }
212 }
213
214 void VideoWidget::notifyVideoLoaded()
215 {
216 updateVideoSize();
217 m_widget->updateGeometry();
218 }
219
220 AbstractVideoRenderer *VideoWidget::switchRendering(AbstractVideoRenderer *current)
221 {
222 const bool toNative = !current->isNative();
223 if (toNative && m_noNativeRendererSupported)
224 return current; //no switch here
225
226 if (!mediaObject())
227 return current;
228
229 //firt we delete the renderer
230 //initialization of the widgets
231 for(int i = 0; i < FILTER_COUNT; ++i) {
232 Filter oldFilter = m_filters[i];
233
234 //Let's create a software renderer
235 AbstractVideoRenderer *renderer = getRenderer(i, toNative ? Native : NonNative, true);
236
237 if (m_mediaObject) {
238 m_mediaObject->switchFilters(i, oldFilter, renderer->getFilter());
239 }
240
241 m_filters[i] = renderer->getFilter();
242 }
243
244 return getRenderer(mediaObject()->currentGraph()->index(), toNative ? Native: NonNative);
245 }
246
247 void VideoWidget::performSoftRendering(const QImage &currentImage)
248 {
249 const int graphIndex = mediaObject()->currentGraph()->index();
250 VideoRendererSoft *r = static_cast<VideoRendererSoft*>(getRenderer(graphIndex, NonNative, true /*autocreation*/));
251 r->setSnapshot(currentImage);
252 r->notifyResize(m_widget->size(), m_aspectRatio, m_scaleMode);
253 r->repaintCurrentFrame(m_widget, m_widget->rect());
254
255 }
256
257 void VideoWidget::setCurrentGraph(int index)
258 {
259 for(int i = 0; i < 2; ++i) {
260 if (AbstractVideoRenderer *renderer = getRenderer(i, Native))
261 renderer->setActive(index == i);
262 }
263
264 //be sure to update all the things that needs an update
265 applyMixerSettings();
266 updateVideoSize();
267
268 AbstractVideoRenderer *r = m_widget->currentRenderer();
269
270 //we determine dynamically if it is native or non native
271 r = getRenderer(index, !r || r->isNative() ? Native : NonNative);
272 if (!r)
273 r = getRenderer(index, NonNative);
274 m_widget->setCurrentRenderer(r);
275 }
276
277
278 Phonon::VideoWidget::AspectRatio VideoWidget::aspectRatio() const
279 {
280 return m_aspectRatio;
281 }
282
283 void VideoWidget::setAspectRatio(Phonon::VideoWidget::AspectRatio aspectRatio)
284 {
285 m_aspectRatio = aspectRatio;
286 updateVideoSize();
287 m_widget->update();
288 }
289
290 Phonon::VideoWidget::ScaleMode VideoWidget::scaleMode() const
291 {
292 return m_scaleMode;
293 }
294
295
296 QWidget *VideoWidget::widget()
297 {
298 return m_widget;
299 }
300
301
302 void VideoWidget::setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode)
303 {
304 m_scaleMode = scaleMode;
305 updateVideoSize();
306 m_widget->update();
307 }
308
309 void VideoWidget::setBrightness(qreal b)
310 {
311 m_brightness = b;
312 applyMixerSettings();
313 }
314
315 void VideoWidget::setContrast(qreal c)
316 {
317 m_contrast = c;
318 applyMixerSettings();
319 }
320
321 void VideoWidget::setHue(qreal h)
322 {
323 m_hue = h;
324 applyMixerSettings();
325 }
326
327 void VideoWidget::setSaturation(qreal s)
328 {
329 m_saturation = s;
330 applyMixerSettings();
331 }
332
333 qreal VideoWidget::brightness() const
334 {
335 return m_brightness;
336 }
337
338
339 qreal VideoWidget::contrast() const
340 {
341 return m_contrast;
342 }
343
344 qreal VideoWidget::hue() const
345 {
346 return m_hue;
347 }
348
349 qreal VideoWidget::saturation() const
350 {
351 return m_saturation;
352 }
353
354
355 AbstractVideoRenderer *VideoWidget::getRenderer(int graphIndex, RendererType type, bool autoCreate)
356 {
357 int index = graphIndex * 2 + type;
358 if (m_renderers[index] == 0 && autoCreate) {
359 AbstractVideoRenderer *renderer = 0;
360 if (type == Native) {
361#ifndef Q_OS_WINCE
362 renderer = new VideoRendererEVR(m_widget);
363 if (renderer->getFilter() == 0) {
364 delete renderer;
365 //EVR not present, let's try VMR
366 renderer = new VideoRendererVMR9(m_widget);
367 if (renderer->getFilter() == 0) {
368 //instanciating the renderer might fail
369 m_noNativeRendererSupported = true;
370 delete renderer;
371 renderer = 0;
372 }
373 }
374#else
375 renderer = new VideoRendererDefault(m_widget);
376 if (renderer->getFilter() == 0) {
377 //instanciating the renderer might fail
378 m_noNativeRendererSupported = true;
379 delete renderer;
380 renderer = 0;
381 }
382#endif
383 }
384
385 if (renderer == 0) {
386 type = NonNative;
387 index = graphIndex * 2 + type;
388 if (m_renderers[index] == 0)
389 renderer = new VideoRendererSoft(m_widget); //this always succeeds
390 else
391 renderer = m_renderers[index];
392 }
393
394 m_renderers[index] = renderer;
395
396 //be sure to update all the things that needs an update
397 applyMixerSettings();
398 updateVideoSize();
399
400 }
401 return m_renderers[index];
402 }
403
404 //this must be called whe nthe node is actually connected
405 void VideoWidget::applyMixerSettings() const
406 {
407 for (int i = 0; i < 4; ++i) {
408 if (AbstractVideoRenderer *renderer = m_renderers[i])
409 renderer->applyMixerSettings(m_brightness, m_contrast, m_hue, m_saturation);
410 }
411 }
412
413 void VideoWidget::connected(BackendNode *, const InputPin&)
414 {
415 //in case of a connection, we simply reapply the mixer settings
416 applyMixerSettings();
417 updateVideoSize();
418 }
419
420 void VideoWidget::updateVideoSize() const
421 {
422 for (int i = 0; i < 4; ++i) {
423 if (AbstractVideoRenderer *renderer = m_renderers[i])
424 renderer->notifyResize(m_widget->size(), m_aspectRatio, m_scaleMode);
425 }
426 }
427
428
429
430 }
431}
432
433#endif //QT_NO_PHONON_VIDEO
434
435QT_END_NAMESPACE
436
437#include "moc_videowidget.cpp"
Note: See TracBrowser for help on using the repository browser.