1
/*  This file is part of the KDE project.
2
3
    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4
5
    This library is free software: you can redistribute it and/or modify
6
    it under the terms of the GNU Lesser General Public License as published by
7
    the Free Software Foundation, either version 2.1 or 3 of the License.
8
9
    This library is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU Lesser General Public License for more details.
13
14
    You should have received a copy of the GNU Lesser General Public License
15
    along with this library.  If not, see <http://www.gnu.org/licenses/>.
16
*/
17
18
#include <QtCore/qglobal.h>
19
#ifdef QT_MAC_USE_COCOA
20
#import <QTKit/QTMovieLayer.h>
21
#endif
22
23
#include "videowidget.h"
24
#include "backendheader.h"
25
#include "quicktimevideoplayer.h"
26
#include "medianode.h"
27
#include "medianodeevent.h"
28
#include "mediaobject.h"
29
30
#include <QtOpenGL/QGLWidget>
31
#include <QtCore/QTime>
32
#include <QtCore/QEvent>
33
#include <QtCore/QCoreApplication>
34
35
#import <AppKit/NSImage.h>
36
#import <QTKit/QTMovieView.h>
37
38
/////////////////////////////////////////////////////////////////////////////////////////
39
40
#ifdef QT_MAC_USE_COCOA // Rendering to a QTMovieView can only be done in Cocoa
41
42
#define VIDEO_TRANSPARENT(m) -(void)m:(NSEvent *)e{[[self superview] m:e];}
43
44
@interface SharedQTMovieView : QTMovieView
45
{
46
@private
47
    Phonon::QT7::QuickTimeVideoPlayer *m_player;
48
    QList<QWidget *> *m_parents;
49
    QWidget *m_window;
50
    QRect *m_drawRect;
51
    bool m_newImageReady;
52
    bool m_usingWindow;
53
}
54
55
- (SharedQTMovieView *) init;
56
- (void) registerParent:(QWidget *)parent;
57
- (void) unregisterParent:(QWidget *)parent;
58
- (void) setDrawRect:(QRect &)rect;
59
- (void) drawVideoFrame:(Phonon::QT7::VideoFrame &)frame forWidget:(QWidget *)widget shareImages:(bool)share;
60
- (void) useOffscreenWindow:(bool)offscreen;
61
- (void) applyDrawRectOnSelf;
62
@end
63
64
/////////////////////////////////////////////////////////////////////////////////////////
65
66
@implementation SharedQTMovieView
67
68
- (SharedQTMovieView *) init
69
{
70
    self = [super initWithFrame:NSZeroRect];
71
	if (self){
72
        [self setControllerVisible:NO];
73
        m_parents = new QList<QWidget *>();
74
        m_drawRect = new QRect(0, 0, 1, 1);
75
        [self applyDrawRectOnSelf];
76
        m_usingWindow = false;
77
	}
78
	return self;
79
}
80
81
- (void) dealloc
82
{
83
    Phonon::QT7::PhononAutoReleasePool pool;
84
    delete m_window;
85
    delete m_drawRect;
86
    delete m_parents;
87
    [super dealloc];
88
}
89
90
- (void) applyDrawRectOnSelf
91
{
92
    NSRect nsrect;
93
    nsrect.origin.x = m_drawRect->x();
94
    nsrect.origin.y = m_drawRect->y();
95
    nsrect.size.width = m_drawRect->width();
96
    nsrect.size.height = m_drawRect->height();
97
    [self setFrame:nsrect];
98
}
99
100
- (void) setDrawRect:(QRect &)rect
101
{
102
    *m_drawRect = rect;
103
    if (!m_usingWindow)
104
        [self applyDrawRectOnSelf];
105
}
106
107
- (void) waitForFrame
108
{
109
    if (m_usingWindow){
110
        QTMovie *movie = [self movie];
111
        if (movie){
112
            // CIImages are expected, but not received.
113
            // Try to wait a couple of seconds for them:
114
            m_newImageReady = false;
115
            float rate = [movie rate];
116
            if (!rate)
117
                [movie setRate:1];
118
            QTime t; t.start();
119
            while (!m_newImageReady && t.elapsed() < 2000)
120
                ;
121
            [movie setRate:rate];
122
        }
123
    }
124
}
125
126
- (void) useOffscreenWindow:(bool)offscreen
127
{
128
    if (offscreen == m_usingWindow)
129
        return;
130
    if (offscreen){
131
        if (!m_window){
132
            m_window = new QWidget;
133
            m_window->setWindowOpacity(0.0);
134
            m_window->show();
135
            m_window->hide();
136
        }
137
        m_usingWindow = true;
138
        [self setDelegate:self];
139
        [self waitForFrame];
140
        foreach(QWidget *w, *m_parents)
141
            w->repaint();
142
        qApp->processEvents();
143
        [self removeFromSuperview];
144
        [(NSView *)m_window->winId() addSubview:self];
145
    } else if (!m_parents->isEmpty()){
146
        m_usingWindow = false;
147
        [self removeFromSuperview];
148
        [(NSView*)m_parents->first()->winId() addSubview:self];
149
        [self setDelegate:0];
150
        [self setDrawRect:*m_drawRect];
151
    }
152
}
153
154
- (void) drawVideoFrame:(Phonon::QT7::VideoFrame &)frame forWidget:(QWidget *)widget shareImages:(bool)share;
155
{
156
    // Detect if the video that produces the frame has changed:
157
    Phonon::QT7::QuickTimeVideoPlayer *player = frame.videoPlayer();
158
    if (player && player->qtMovie() != [self movie]){
159
        m_player = player;
160
        [self setMovie:player->qtMovie()];
161
        [self waitForFrame];
162
    }
163
164
    [self useOffscreenWindow:(share || m_parents->size() > 1)];
165
    if (m_usingWindow)
166
        widget->update();
167
}
168
169
// Override this method so that the movie doesn't stop if
170
// the window becomes invisible
171
- (void)viewWillMoveToWindow:(NSWindow *)newWindow
172
{
173
    Q_UNUSED(newWindow);
174
}
175
176
- (CIImage *) view:(QTMovieView *)view willDisplayImage:(CIImage *)img
177
{
178
	// This method is called from QTMovieView just
179
	// before the image will be drawn.
180
    Q_UNUSED(view);
181
    m_player->setPrimaryRenderingCIImage(img);
182
    m_newImageReady = true;
183
	return img;
184
}
185
186
- (void) registerParent:(QWidget *)parent
187
{
188
    if (m_parents->contains(parent))
189
        return;
190
    m_parents->append(parent);
191
    if (m_parents->size() == 1){
192
        Phonon::QT7::PhononAutoReleasePool pool;
193
        m_usingWindow = true;
194
        [self applyDrawRectOnSelf];
195
        [self useOffscreenWindow:NO];
196
    }
197
}
198
199
- (void) unregisterParent:(QWidget *)parent
200
{
201
    m_parents->removeAll(parent);
202
    if (m_parents->size() == 1)
203
        [self applyDrawRectOnSelf];
204
}
205
206
VIDEO_TRANSPARENT(mouseDown);
207
VIDEO_TRANSPARENT(mouseDragged);
208
VIDEO_TRANSPARENT(mouseUp);
209
VIDEO_TRANSPARENT(mouseMoved);
210
VIDEO_TRANSPARENT(mouseEntered);
211
VIDEO_TRANSPARENT(mouseExited);
212
VIDEO_TRANSPARENT(rightMouseDown);
213
VIDEO_TRANSPARENT(rightMouseDragged);
214
VIDEO_TRANSPARENT(rightMouseUp);
215
VIDEO_TRANSPARENT(otherMouseDown);
216
VIDEO_TRANSPARENT(otherMouseDragged);
217
VIDEO_TRANSPARENT(otherMouseUp);
218
VIDEO_TRANSPARENT(keyDown);
219
VIDEO_TRANSPARENT(keyUp);
220
VIDEO_TRANSPARENT(scrollWheel)
221
222
@end
223
224
#endif // QT_MAC_USE_COCOA
225
226
/////////////////////////////////////////////////////////////////////////////////////////
227
228
QT_BEGIN_NAMESPACE
229
230
namespace Phonon
231
{
232
namespace QT7
233
{
234
235
class IVideoRenderDrawWidget
236
{
237
public:
238
	virtual ~IVideoRenderDrawWidget(){}
239
	virtual void setVideoFrame(VideoFrame &) = 0;
240
	virtual void setDrawFrameRect(const QRect &) = 0;
241
	virtual void updateVideoOutputCount(int){}
242
	virtual void setMovieIsPaused(bool){}
243
};
244
245
/////////////////////////////////////////////////////////////////////////////////////////
246
247
QGLWidget *PhononSharedQGLWidget(){
248
	static QGLWidget *glWidget = 0;
249
	if (!glWidget)
250
		glWidget = new QGLWidget();
251
	return glWidget;
252
}
253
254
/////////////////////////////////////////////////////////////////////////////////////////
255
256
class RenderOpenGL : public QGLWidget, public IVideoRenderDrawWidget
257
{
258
public:
259
    VideoFrame m_currentFrame;
260
    QRect m_drawFrameRect;
261
262
    RenderOpenGL(QWidget *parent, const QGLFormat &format, const QSize &size) : QGLWidget(format, parent, PhononSharedQGLWidget())
263
    {
264
        resize(size);
265
        setAutoFillBackground(false);
266
        show();
267
    }
268
269
    void initializeGL()
270
    {
271
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
272
    }
273
274
    void resizeGL(int w, int h)
275
    {
276
        glMatrixMode(GL_MODELVIEW);
277
        glLoadIdentity();
278
        glMatrixMode(GL_PROJECTION);
279
        glLoadIdentity();
280
        glViewport(0, 0, GLsizei(w), GLsizei(h));
281
        glOrtho(0, GLsizei(w), 0, GLsizei(h), -1, 1);
282
        updateGL();
283
    }
284
285
    void paintGL()
286
    {
287
        glClear(GL_COLOR_BUFFER_BIT);
288
        m_currentFrame.drawCVTexture(m_drawFrameRect);
289
    }
290
291
    void setVideoFrame(VideoFrame &frame)
292
    {
293
        m_currentFrame = frame;
294
        makeCurrent();
295
        paintGL();
296
        swapBuffers();
297
    }
298
299
    void setDrawFrameRect(const QRect &rect)
300
    {
301
        m_drawFrameRect = rect;
302
    }
303
};
304
305
/////////////////////////////////////////////////////////////////////////////////////////
306
307
class RenderQTMovieView : public QWidget, public IVideoRenderDrawWidget
308
{
309
public:
310
#if defined(QT_MAC_USE_COCOA)
311
	QRect m_drawRect;
312
	VideoFrame m_videoFrame;
313
    SharedQTMovieView *m_currentView;
314
    bool m_setDrawRectPending;
315
    bool m_share;
316
317
    RenderQTMovieView(bool share, QWidget *parent, const QSize &size=QSize()) : QWidget(parent), m_currentView(0)
318
    {
319
        m_setDrawRectPending = true;
320
        m_share = share;
321
        setAutoFillBackground(false);
322
        if (share){
323
            // In 'share' mode, this widget will only make sure
324
            // that CIIImages are produced, and not actually
325
            // draw anything:
326
            hide();
327
        } else {
328
            resize(size);
329
            show();
330
        }
331
    }
332
333
    ~RenderQTMovieView()
334
    {
335
        [m_currentView unregisterParent:this];
336
    }
337
338
    void showEvent(QShowEvent *)
339
    {
340
        if (m_share)
341
            return;
342
        [m_currentView registerParent:this];
343
    }
344
345
    void hideEvent(QHideEvent *)
346
    {
347
        if (m_share)
348
            return;
349
        [m_currentView unregisterParent:this];
350
    }
351
352
    void paintEvent(QPaintEvent *)
353
    {
354
        if (m_share)
355
            return;
356
		QPainter p(this);
357
		p.fillRect(rect(), Qt::black);
358
        m_videoFrame.drawCIImage(m_drawRect);
359
    }
360
361
	void updateVideoOutputCount(int count)
362
	{
363
		Q_UNUSED(count);
364
	}
365
366
	void setMovieIsPaused(bool paused)
367
	{
368
        Q_UNUSED(paused);
369
	}
370
371
    void setVideoFrame(VideoFrame &frame)
372
    {
373
        m_videoFrame = frame;
374
375
        if (!m_videoFrame.isEmpty()){
376
            Phonon::QT7::QuickTimeVideoPlayer *player = m_videoFrame.videoPlayer();
377
            if (!player->m_primaryRenderingTarget){
378
                // First movie view. Create the shared resource:
379
                SharedQTMovieView *view = [[[SharedQTMovieView alloc] init] autorelease];
380
                player->setPrimaryRenderingTarget(view);
381
            }
382
383
            SharedQTMovieView *view = static_cast<SharedQTMovieView *>(player->m_primaryRenderingTarget);
384
            if (!m_share && view != m_currentView){
385
                [m_currentView unregisterParent:this];
386
                m_currentView = view;
387
                [m_currentView registerParent:this];
388
            }
389
390
            [view drawVideoFrame:m_videoFrame forWidget:this shareImages:m_share || m_videoFrame.hasColorAdjustments()];
391
392
            if (m_setDrawRectPending){
393
                m_setDrawRectPending = false;
394
                [view setDrawRect:m_drawRect];
395
            }
396
        }
397
    }
398
399
    void setDrawFrameRect(const QRect &rect)
400
    {
401
        m_drawRect = rect;
402
        Phonon::QT7::QuickTimeVideoPlayer *player = m_videoFrame.videoPlayer();
403
        if (player && player->m_primaryRenderingTarget){
404
            SharedQTMovieView *view = static_cast<SharedQTMovieView *>(player->m_primaryRenderingTarget);
405
            [view setDrawRect:m_drawRect];
406
        } else
407
            m_setDrawRectPending = true;
408
    }
409
410
#else // QT_MAC_USE_COCOA == false
411
	RenderQTMovieView(bool, QWidget *, const QSize& = QSize()){}
412
	void setVideoFrame(VideoFrame &){}
413
	void setDrawFrameRect(const QRect &){}
414
#endif
415
};
416
417
/////////////////////////////////////////////////////////////////////////////////////////
418
419
class RenderQTMovieLayer : public QWidget, public IVideoRenderDrawWidget
420
{
421
public:
422
#ifdef QT_MAC_USE_COCOA
423
    QTMovieLayer *m_movieLayer;
424
425
    RenderQTMovieLayer(QWidget *parent, const QSize&) : QWidget(parent)
426
    {
427
		PhononAutoReleasePool pool;
428
        setAutoFillBackground(false);
429
        m_movieLayer = 0;
430
        [(NSView *)winId() setWantsLayer:YES];
431
    }
432
433
    void setVideoFrame(VideoFrame &frame)
434
    {
435
        QuickTimeVideoPlayer *player = frame.videoPlayer();
436
        if (!player || player->qtMovie() == [m_movieLayer movie])
437
            return;
438
439
        if (m_movieLayer)
440
            [m_movieLayer setMovie:player->qtMovie()];
441
        else {
442
            m_movieLayer = [QTMovieLayer layerWithMovie:player->qtMovie()];
443
            [(NSView *)winId() setLayer:m_movieLayer];
444
        }
445
    }
446
447
    void setDrawFrameRect(const QRect &rect)
448
    {
449
        CGRect frame = m_movieLayer.frame;
450
        frame.origin.x = rect.x();
451
        frame.origin.y = rect.y();
452
        frame.size.width = rect.width();
453
        frame.size.height = rect.height();
454
        m_movieLayer.frame = frame;
455
    }
456
457
#else // QT_MAC_USE_COCOA == false
458
	RenderQTMovieLayer(QWidget *, const QSize&){}
459
	void setVideoFrame(VideoFrame &){}
460
	void setDrawFrameRect(const QRect &){}
461
#endif
462
};
463
464
/////////////////////////////////////////////////////////////////////////////////////////
465
466
class VideoRenderWidget : public QWidget
467
{
468
public:
469
    enum RenderSystem {	RS_NoRendering	= 0,
470
						RS_QGLWidget	= 1,
471
						RS_QPainter		= 2,
472
						RS_CIImage		= 3,
473
						RS_CVTexture	= 4,
474
						RS_QImage		= 5,
475
						RS_QTMovieView	= 6,
476
						RS_QTMovieLayer = 7
477
	} m_renderSystem;
478
479
    VideoFrame m_currentFrame;
480
    QRect m_movieFrameRect;
481
    QRect m_drawFrameRect;
482
    Phonon::VideoWidget::ScaleMode m_scaleMode;
483
    Phonon::VideoWidget::AspectRatio m_aspect;
484
	IVideoRenderDrawWidget *m_renderDrawWidget;
485
486
    qreal m_brightness;
487
    qreal m_contrast;
488
    qreal m_hue;
489
    qreal m_saturation;
490
    qreal m_opacity;
491
492
    VideoRenderWidget() : QWidget(0),
493
        m_scaleMode(Phonon::VideoWidget::FitInView), m_aspect(Phonon::VideoWidget::AspectRatioAuto)
494
    {
495
		PhononAutoReleasePool pool;
496
        m_brightness = 0;
497
        m_contrast = 0;
498
        m_hue = 0;
499
        m_saturation = 0;
500
        m_opacity = 1;
501
		m_renderDrawWidget = 0;
502
		m_renderSystem = RS_NoRendering;
503
504
        setAutoFillBackground(false);
505
        updateDrawFrameRect();
506
    }
507
508
    RenderSystem selectBestRenderSystem(){
509
        if (!isVisible())
510
            return RS_NoRendering;
511
        else if (window() && window()->testAttribute(Qt::WA_DontShowOnScreen))
512
            return RS_QPainter;
513
        else {
514
#ifdef QUICKTIME_C_API_AVAILABLE
515
            return RS_QGLWidget;
516
#else
517
            return RS_QTMovieView;
518
#endif
519
        }
520
    }
521
522
    void setRenderSystem(RenderSystem renderSystem){
523
		PhononAutoReleasePool pool;
524
		static QString userSystem = qgetenv("PHONON_RENDER_SYSTEM");
525
	    if (!userSystem.isEmpty())
526
			renderSystem = RenderSystem(userSystem.toInt());
527
528
        if (m_renderSystem == renderSystem)
529
            return;
530
531
        m_renderSystem = renderSystem;
532
        if (m_renderDrawWidget){
533
            delete m_renderDrawWidget;
534
			m_renderDrawWidget = 0;
535
		}
536
537
        switch (m_renderSystem){
538
            case RS_QGLWidget:{
539
			    QGLFormat format = QGLFormat::defaultFormat();
540
			    format.setSwapInterval(1); // Vertical sync (avoid tearing)
541
			    m_renderDrawWidget = new RenderOpenGL(this, format, size());
542
                break;}
543
            case RS_QTMovieView:{
544
			    m_renderDrawWidget = new RenderQTMovieView(false, this, size());
545
                break;}
546
            case RS_QTMovieLayer:{
547
			    m_renderDrawWidget = new RenderQTMovieLayer(this, size());
548
				break;}
549
            case RS_QPainter:
550
			case RS_CIImage:
551
			case RS_CVTexture:
552
			case RS_QImage:
553
#ifndef QUICKTIME_C_API_AVAILABLE
554
                // On cocoa-64, let QTMovieView produce
555
                // video frames for us:
556
				m_renderDrawWidget = new RenderQTMovieView(true, this);
557
#endif
558
				break;
559
            case RS_NoRendering:
560
                break;
561
        }
562
563
		if (m_renderDrawWidget){
564
            m_renderDrawWidget->setVideoFrame(m_currentFrame);
565
            m_renderDrawWidget->setDrawFrameRect(m_drawFrameRect);
566
        }
567
    }
568
569
    QSize sizeHint() const
570
    {
571
        return m_movieFrameRect.size();
572
    }
573
574
    bool event(QEvent *event)
575
    {
576
        switch (event->type()){
577
            // Try to detect if one of this objects
578
            // anchestors might have changed:
579
            case QEvent::Resize:{
580
                PhononAutoReleasePool pool;
581
                updateDrawFrameRect();
582
                if (m_renderDrawWidget)
583
                    dynamic_cast<QWidget *>(m_renderDrawWidget)->resize(size());
584
                break; }
585
            case QEvent::Paint:{
586
                PhononAutoReleasePool pool;
587
                float opacity = parentWidget() ? parentWidget()->windowOpacity() : 1;
588
                switch (m_renderSystem){
589
                    case RS_QPainter:{
590
                        QPainter p(this);
591
                        p.fillRect(rect(), Qt::black);
592
                        if (p.paintEngine()->type() == QPaintEngine::OpenGL)
593
                            m_currentFrame.drawCVTexture(m_drawFrameRect, opacity);
594
                        else
595
							m_currentFrame.drawQImage(&p, m_drawFrameRect);
596
                        break; }
597
					case RS_CIImage:
598
                        m_currentFrame.drawCIImage(m_drawFrameRect, opacity);
599
						break;
600
                    case RS_CVTexture:
601
	                   m_currentFrame.drawCVTexture(m_drawFrameRect, opacity);
602
					   break;
603
					case RS_QImage:{
604
                        QPainter p(this);
605
                        p.fillRect(rect(), Qt::black);
606
						m_currentFrame.drawQImage(&p, m_drawFrameRect);
607
                        break; }
608
                    case RS_QGLWidget:
609
                    case RS_QTMovieView:
610
                    case RS_QTMovieLayer:
611
                        // draw in separate widget
612
                        break;
613
                    case RS_NoRendering:
614
                        QPainter p(this);
615
                        p.fillRect(rect(), Qt::black);
616
                        break;
617
                }
618
                break; }
619
            default:
620
                break;
621
        }
622
623
        return QWidget::event(event);
624
    }
625
626
    void setVideoFrame(VideoFrame &frame)
627
    {
628
		PhononAutoReleasePool pool;
629
        m_currentFrame = frame;
630
        m_currentFrame.setColors(m_brightness, m_contrast, m_hue, m_saturation);
631
632
		if (m_renderDrawWidget)
633
			m_renderDrawWidget->setVideoFrame(m_currentFrame);
634
635
        setRenderSystem(selectBestRenderSystem());
636
        switch (m_renderSystem){
637
            case RS_QGLWidget:
638
            case RS_QTMovieView:
639
            case RS_QTMovieLayer:
640
            case RS_NoRendering:
641
                break;
642
			case RS_CIImage:
643
			case RS_CVTexture:
644
			case RS_QImage:
645
            case RS_QPainter:
646
                repaint();
647
                break;
648
        }
649
    }
650
651
    void updateVideoFrame()
652
    {
653
        setVideoFrame(m_currentFrame);
654
    }
655
656
    void setMovieRect(const QRect &mrect)
657
    {
658
        if (mrect == m_movieFrameRect)
659
            return;
660
        m_movieFrameRect = mrect;
661
        updateDrawFrameRect();
662
        updateGeometry();
663
        if (isVisible())
664
            qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
665
    }
666
667
    void setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode)
668
    {
669
        m_scaleMode = scaleMode;
670
        updateDrawFrameRect();
671
        updateVideoFrame();
672
        repaint();
673
    }
674
675
    void setAspectRatio(Phonon::VideoWidget::AspectRatio aspect)
676
    {
677
        m_aspect = aspect;
678
        updateDrawFrameRect();
679
        updateVideoFrame();
680
        repaint();
681
    }
682
683
	void updateVideoOutputCount(int count)
684
	{
685
		if (m_renderDrawWidget)
686
			m_renderDrawWidget->updateVideoOutputCount(count);
687
	}
688
689
	void setMovieIsPaused(bool paused)
690
	{
691
		if (m_renderDrawWidget)
692
			m_renderDrawWidget->setMovieIsPaused(paused);
693
	}
694
695
    void updateDrawFrameRect()
696
    {
697
        if (m_movieFrameRect.width() <= 0 || m_movieFrameRect.height() <= 0)
698
            m_movieFrameRect = QRect(0, 0, 640, 480);
699
700
        // Set m_drawFrameRect to be the size of the smallest possible
701
        // rect conforming to the aspect and containing the whole frame:
702
        switch(m_aspect){
703
        case Phonon::VideoWidget::AspectRatioWidget:
704
            m_drawFrameRect = rect();
705
            break;
706
        case Phonon::VideoWidget::AspectRatio4_3:
707
            m_drawFrameRect = scaleToAspect(m_movieFrameRect, 4, 3);
708
            break;
709
        case Phonon::VideoWidget::AspectRatio16_9:
710
            m_drawFrameRect = scaleToAspect(m_movieFrameRect, 16, 9);
711
            break;
712
        case Phonon::VideoWidget::AspectRatioAuto:
713
        default:
714
            m_drawFrameRect = m_movieFrameRect;
715
            break;
716
        }
717
718
        // Scale m_drawFrameRect to fill the widget
719
        // without breaking aspect:
720
        int widgetWidth = rect().width();
721
        int widgetHeight = rect().height();
722
        int frameWidth = widgetWidth;
723
        int frameHeight = m_drawFrameRect.height() * float(widgetWidth) / float(m_drawFrameRect.width());
724
725
        switch(m_scaleMode){
726
        case Phonon::VideoWidget::ScaleAndCrop:
727
            if (frameHeight < widgetHeight){
728
                frameWidth *= float(widgetHeight) / float(frameHeight);
729
                frameHeight = widgetHeight;
730
            }
731
            break;
732
        case Phonon::VideoWidget::FitInView:
733
        default:
734
            if (frameHeight > widgetHeight){
735
                frameWidth *= float(widgetHeight) / float(frameHeight);
736
                frameHeight = widgetHeight;
737
            }
738
            break;
739
        }
740
741
        m_drawFrameRect.setSize(QSize(frameWidth, frameHeight));
742
        m_drawFrameRect.moveTo((widgetWidth - frameWidth) / 2.0f, (widgetHeight - frameHeight) / 2.0f);
743
744
		if (m_renderDrawWidget)
745
			m_renderDrawWidget->setDrawFrameRect(m_drawFrameRect);
746
    }
747
748
    QRect scaleToAspect(QRect srcRect, int w, int h)
749
    {
750
        int width = srcRect.width();
751
        int height = srcRect.width() * (float(h) / float(w));
752
        if (height > srcRect.height()){
753
            height = srcRect.height();
754
            width = srcRect.height() * (float(w) / float(h));
755
        }
756
        return QRect(0, 0, width, height);
757
    }
758
};
759
760
/////////////////////////////////////////////////////////////////////////////////////////
761
762
VideoWidget::VideoWidget(QObject *parent) : MediaNode(VideoSink, parent)
763
{
764
    m_videoRenderWidget = new VideoRenderWidget();
765
}
766
767
VideoWidget::~VideoWidget()
768
{
769
    delete m_videoRenderWidget;
770
}
771
772
QWidget *VideoWidget::widget()
773
{
774
    IMPLEMENTED;
775
    return m_videoRenderWidget;
776
}
777
778
Phonon::VideoWidget::AspectRatio VideoWidget::aspectRatio() const
779
{
780
    IMPLEMENTED;
781
    return  m_videoRenderWidget->m_aspect;
782
}
783
784
void VideoWidget::setAspectRatio(Phonon::VideoWidget::AspectRatio aspect)
785
{
786
    IMPLEMENTED;
787
    m_videoRenderWidget->setAspectRatio(aspect);
788
}
789
790
Phonon::VideoWidget::ScaleMode VideoWidget::scaleMode() const
791
{
792
    IMPLEMENTED;
793
    return m_videoRenderWidget->m_scaleMode;
794
}
795
796
void VideoWidget::setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode)
797
{
798
    IMPLEMENTED;
799
    m_videoRenderWidget->setScaleMode(scaleMode);
800
}
801
802
qreal VideoWidget::brightness() const
803
{
804
    IMPLEMENTED;
805
    return m_videoRenderWidget->m_brightness;
806
}
807
808
void VideoWidget::setBrightness(qreal value)
809
{
810
    IMPLEMENTED;
811
    m_videoRenderWidget->m_brightness = value;
812
    if (m_owningMediaObject && m_owningMediaObject->state() == Phonon::PausedState)
813
        m_videoRenderWidget->updateVideoFrame();
814
}
815
816
qreal VideoWidget::contrast() const
817
{
818
    IMPLEMENTED;
819
    return m_videoRenderWidget->m_contrast;
820
}
821
822
void VideoWidget::setContrast(qreal value)
823
{
824
    IMPLEMENTED;
825
    m_videoRenderWidget->m_contrast = value;
826
    if (m_owningMediaObject && m_owningMediaObject->state() == Phonon::PausedState)
827
        m_videoRenderWidget->updateVideoFrame();
828
}
829
830
qreal VideoWidget::hue() const
831
{
832
    IMPLEMENTED;
833
    return m_videoRenderWidget->m_hue;
834
}
835
836
void VideoWidget::setHue(qreal value)
837
{
838
    IMPLEMENTED;
839
    m_videoRenderWidget->m_hue = value;
840
    if (m_owningMediaObject && m_owningMediaObject->state() == Phonon::PausedState)
841
        m_videoRenderWidget->updateVideoFrame();
842
}
843
844
qreal VideoWidget::saturation() const
845
{
846
    IMPLEMENTED;
847
    return m_videoRenderWidget->m_saturation;
848
}
849
850
void VideoWidget::setSaturation(qreal value)
851
{
852
    IMPLEMENTED;
853
    m_videoRenderWidget->m_saturation = value;
854
    if (m_owningMediaObject && m_owningMediaObject->state() == Phonon::PausedState)
855
        m_videoRenderWidget->updateVideoFrame();
856
}
857
858
void VideoWidget::mediaNodeEvent(const MediaNodeEvent *event)
859
{
860
    switch (event->type()){
861
    case MediaNodeEvent::VideoFrameSizeChanged:
862
        m_videoRenderWidget->setMovieRect(*static_cast<QRect *>(event->data()));
863
        break;
864
	case MediaNodeEvent::VideoOutputCountChanged:
865
	     m_videoRenderWidget->updateVideoOutputCount(*static_cast<int *>(event->data()));
866
	     break;
867
	case MediaNodeEvent::MediaPlaying:
868
	     m_videoRenderWidget->setMovieIsPaused(!(*static_cast<bool *>(event->data())));
869
	     break;
870
	default:
871
        break;
872
    }
873
}
874
875
void VideoWidget::updateVideo(VideoFrame &frame){
876
	PhononAutoReleasePool pool;
877
    m_videoRenderWidget->setVideoFrame(frame);
878
    MediaNode::updateVideo(frame);
879
}
880
881
}} // namespace Phonon::QT7
882
883
QT_END_NAMESPACE
884
885
#include "moc_videowidget.cpp"