src/3rdparty/phonon/qt7/videowidget.mm
changeset 0 1918ee327afb
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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         gluOrtho2D(0, GLsizei(w), 0, GLsizei(h));
       
   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         m_movieLayer.frame.origin.x = rect.x();
       
   450         m_movieLayer.frame.origin.y = rect.y();
       
   451         m_movieLayer.frame.size.width = rect.width();
       
   452         m_movieLayer.frame.size.height = rect.height();
       
   453     }
       
   454 
       
   455 #else // QT_MAC_USE_COCOA == false
       
   456 	RenderQTMovieLayer(QWidget *, const QSize&){}
       
   457 	void setVideoFrame(VideoFrame &){}
       
   458 	void setDrawFrameRect(const QRect &){}
       
   459 #endif
       
   460 };
       
   461 
       
   462 /////////////////////////////////////////////////////////////////////////////////////////
       
   463 
       
   464 class VideoRenderWidget : public QWidget
       
   465 {
       
   466 public:
       
   467     enum RenderSystem {	RS_NoRendering	= 0,
       
   468 						RS_QGLWidget	= 1,
       
   469 						RS_QPainter		= 2,
       
   470 						RS_CIImage		= 3,
       
   471 						RS_CVTexture	= 4,
       
   472 						RS_QImage		= 5,
       
   473 						RS_QTMovieView	= 6,
       
   474 						RS_QTMovieLayer = 7
       
   475 	} m_renderSystem;
       
   476 
       
   477     VideoFrame m_currentFrame;
       
   478     QRect m_movieFrameRect;
       
   479     QRect m_drawFrameRect;
       
   480     Phonon::VideoWidget::ScaleMode m_scaleMode;
       
   481     Phonon::VideoWidget::AspectRatio m_aspect;
       
   482 	IVideoRenderDrawWidget *m_renderDrawWidget;
       
   483 
       
   484     qreal m_brightness;
       
   485     qreal m_contrast;
       
   486     qreal m_hue;
       
   487     qreal m_saturation;
       
   488     qreal m_opacity;
       
   489 
       
   490     VideoRenderWidget() : QWidget(0),
       
   491         m_scaleMode(Phonon::VideoWidget::FitInView), m_aspect(Phonon::VideoWidget::AspectRatioAuto)
       
   492     {
       
   493 		PhononAutoReleasePool pool;
       
   494         m_brightness = 0;
       
   495         m_contrast = 0;
       
   496         m_hue = 0;
       
   497         m_saturation = 0;
       
   498         m_opacity = 1;
       
   499 		m_renderDrawWidget = 0;
       
   500 		m_renderSystem = RS_NoRendering;
       
   501 
       
   502         setAutoFillBackground(false);
       
   503         updateDrawFrameRect();
       
   504     }
       
   505 
       
   506     RenderSystem selectBestRenderSystem(){
       
   507         if (!isVisible())
       
   508             return RS_NoRendering;
       
   509         else if (window() && window()->testAttribute(Qt::WA_DontShowOnScreen))
       
   510             return RS_QPainter;
       
   511         else {
       
   512 #ifdef QUICKTIME_C_API_AVAILABLE
       
   513             return RS_QGLWidget;
       
   514 #else
       
   515             return RS_QTMovieView;
       
   516 #endif
       
   517         }
       
   518     }
       
   519 
       
   520     void setRenderSystem(RenderSystem renderSystem){
       
   521 		PhononAutoReleasePool pool;
       
   522 		static QString userSystem = qgetenv("PHONON_RENDER_SYSTEM");
       
   523 	    if (!userSystem.isEmpty())
       
   524 			renderSystem = RenderSystem(userSystem.toInt());
       
   525 
       
   526         if (m_renderSystem == renderSystem)
       
   527             return;
       
   528 
       
   529         m_renderSystem = renderSystem;
       
   530         if (m_renderDrawWidget){
       
   531             delete m_renderDrawWidget;
       
   532 			m_renderDrawWidget = 0;
       
   533 		}
       
   534 
       
   535         switch (m_renderSystem){
       
   536             case RS_QGLWidget:{
       
   537 			    QGLFormat format = QGLFormat::defaultFormat();
       
   538 			    format.setSwapInterval(1); // Vertical sync (avoid tearing)
       
   539 			    m_renderDrawWidget = new RenderOpenGL(this, format, size());
       
   540                 break;}
       
   541             case RS_QTMovieView:{
       
   542 			    m_renderDrawWidget = new RenderQTMovieView(false, this, size());
       
   543                 break;}
       
   544             case RS_QTMovieLayer:{
       
   545 			    m_renderDrawWidget = new RenderQTMovieLayer(this, size());
       
   546 				break;}
       
   547             case RS_QPainter:
       
   548 			case RS_CIImage:
       
   549 			case RS_CVTexture:
       
   550 			case RS_QImage:
       
   551 #ifndef QUICKTIME_C_API_AVAILABLE
       
   552                 // On cocoa-64, let QTMovieView produce
       
   553                 // video frames for us:
       
   554 				m_renderDrawWidget = new RenderQTMovieView(true, this);
       
   555 #endif
       
   556 				break;
       
   557             case RS_NoRendering:
       
   558                 break;
       
   559         }
       
   560 
       
   561 		if (m_renderDrawWidget){
       
   562             m_renderDrawWidget->setVideoFrame(m_currentFrame);
       
   563             m_renderDrawWidget->setDrawFrameRect(m_drawFrameRect);
       
   564         }
       
   565     }
       
   566 
       
   567     QSize sizeHint() const
       
   568     {
       
   569         return m_movieFrameRect.size();
       
   570     }
       
   571 
       
   572     bool event(QEvent *event)
       
   573     {
       
   574         switch (event->type()){
       
   575             // Try to detect if one of this objects
       
   576             // anchestors might have changed:
       
   577             case QEvent::Resize:{
       
   578                 PhononAutoReleasePool pool;
       
   579                 updateDrawFrameRect();
       
   580                 if (m_renderDrawWidget)
       
   581                     dynamic_cast<QWidget *>(m_renderDrawWidget)->resize(size());
       
   582                 break; }
       
   583             case QEvent::Paint:{
       
   584                 PhononAutoReleasePool pool;
       
   585                 float opacity = parentWidget() ? parentWidget()->windowOpacity() : 1;
       
   586                 switch (m_renderSystem){
       
   587                     case RS_QPainter:{
       
   588                         QPainter p(this);
       
   589                         p.fillRect(rect(), Qt::black);
       
   590                         if (p.paintEngine()->type() == QPaintEngine::OpenGL)
       
   591                             m_currentFrame.drawCVTexture(m_drawFrameRect, opacity);
       
   592                         else
       
   593 							m_currentFrame.drawQImage(&p, m_drawFrameRect);
       
   594                         break; }
       
   595 					case RS_CIImage:
       
   596                         m_currentFrame.drawCIImage(m_drawFrameRect, opacity);
       
   597 						break;
       
   598                     case RS_CVTexture:
       
   599 	                   m_currentFrame.drawCVTexture(m_drawFrameRect, opacity);
       
   600 					   break;
       
   601 					case RS_QImage:{
       
   602                         QPainter p(this);
       
   603                         p.fillRect(rect(), Qt::black);
       
   604 						m_currentFrame.drawQImage(&p, m_drawFrameRect);
       
   605                         break; }
       
   606                     case RS_QGLWidget:
       
   607                     case RS_QTMovieView:
       
   608                     case RS_QTMovieLayer:
       
   609                         // draw in separate widget
       
   610                         break;
       
   611                     case RS_NoRendering:
       
   612                         QPainter p(this);
       
   613                         p.fillRect(rect(), Qt::black);
       
   614                         break;
       
   615                 }
       
   616                 break; }
       
   617             default:
       
   618                 break;
       
   619         }
       
   620 
       
   621         return QWidget::event(event);
       
   622     }
       
   623 
       
   624     void setVideoFrame(VideoFrame &frame)
       
   625     {
       
   626 		PhononAutoReleasePool pool;
       
   627         m_currentFrame = frame;
       
   628         m_currentFrame.setColors(m_brightness, m_contrast, m_hue, m_saturation);
       
   629 
       
   630 		if (m_renderDrawWidget)
       
   631 			m_renderDrawWidget->setVideoFrame(m_currentFrame);
       
   632 
       
   633         setRenderSystem(selectBestRenderSystem());
       
   634         switch (m_renderSystem){
       
   635             case RS_QGLWidget:
       
   636             case RS_QTMovieView:
       
   637             case RS_QTMovieLayer:
       
   638             case RS_NoRendering:
       
   639                 break;
       
   640 			case RS_CIImage:
       
   641 			case RS_CVTexture:
       
   642 			case RS_QImage:
       
   643             case RS_QPainter:
       
   644                 repaint();
       
   645                 break;
       
   646         }
       
   647     }
       
   648 
       
   649     void updateVideoFrame()
       
   650     {
       
   651         setVideoFrame(m_currentFrame);
       
   652     }
       
   653 
       
   654     void setMovieRect(const QRect &mrect)
       
   655     {
       
   656         if (mrect == m_movieFrameRect)
       
   657             return;
       
   658         m_movieFrameRect = mrect;
       
   659         updateDrawFrameRect();
       
   660         updateGeometry();
       
   661         if (isVisible())
       
   662             qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
       
   663     }
       
   664 
       
   665     void setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode)
       
   666     {
       
   667         m_scaleMode = scaleMode;
       
   668         updateDrawFrameRect();
       
   669         updateVideoFrame();
       
   670         repaint();
       
   671     }
       
   672 
       
   673     void setAspectRatio(Phonon::VideoWidget::AspectRatio aspect)
       
   674     {
       
   675         m_aspect = aspect;
       
   676         updateDrawFrameRect();
       
   677         updateVideoFrame();
       
   678         repaint();
       
   679     }
       
   680 
       
   681 	void updateVideoOutputCount(int count)
       
   682 	{
       
   683 		if (m_renderDrawWidget)
       
   684 			m_renderDrawWidget->updateVideoOutputCount(count);
       
   685 	}
       
   686 
       
   687 	void setMovieIsPaused(bool paused)
       
   688 	{
       
   689 		if (m_renderDrawWidget)
       
   690 			m_renderDrawWidget->setMovieIsPaused(paused);
       
   691 	}
       
   692 
       
   693     void updateDrawFrameRect()
       
   694     {
       
   695         if (m_movieFrameRect.width() <= 0 || m_movieFrameRect.height() <= 0)
       
   696             m_movieFrameRect = QRect(0, 0, 640, 480);
       
   697 
       
   698         // Set m_drawFrameRect to be the size of the smallest possible
       
   699         // rect conforming to the aspect and containing the whole frame:
       
   700         switch(m_aspect){
       
   701         case Phonon::VideoWidget::AspectRatioWidget:
       
   702             m_drawFrameRect = rect();
       
   703             break;
       
   704         case Phonon::VideoWidget::AspectRatio4_3:
       
   705             m_drawFrameRect = scaleToAspect(m_movieFrameRect, 4, 3);
       
   706             break;
       
   707         case Phonon::VideoWidget::AspectRatio16_9:
       
   708             m_drawFrameRect = scaleToAspect(m_movieFrameRect, 16, 9);
       
   709             break;
       
   710         case Phonon::VideoWidget::AspectRatioAuto:
       
   711         default:
       
   712             m_drawFrameRect = m_movieFrameRect;
       
   713             break;
       
   714         }
       
   715 
       
   716         // Scale m_drawFrameRect to fill the widget
       
   717         // without breaking aspect:
       
   718         int widgetWidth = rect().width();
       
   719         int widgetHeight = rect().height();
       
   720         int frameWidth = widgetWidth;
       
   721         int frameHeight = m_drawFrameRect.height() * float(widgetWidth) / float(m_drawFrameRect.width());
       
   722 
       
   723         switch(m_scaleMode){
       
   724         case Phonon::VideoWidget::ScaleAndCrop:
       
   725             if (frameHeight < widgetHeight){
       
   726                 frameWidth *= float(widgetHeight) / float(frameHeight);
       
   727                 frameHeight = widgetHeight;
       
   728             }
       
   729             break;
       
   730         case Phonon::VideoWidget::FitInView:
       
   731         default:
       
   732             if (frameHeight > widgetHeight){
       
   733                 frameWidth *= float(widgetHeight) / float(frameHeight);
       
   734                 frameHeight = widgetHeight;
       
   735             }
       
   736             break;
       
   737         }
       
   738 
       
   739         m_drawFrameRect.setSize(QSize(frameWidth, frameHeight));
       
   740         m_drawFrameRect.moveTo((widgetWidth - frameWidth) / 2.0f, (widgetHeight - frameHeight) / 2.0f);
       
   741 
       
   742 		if (m_renderDrawWidget)
       
   743 			m_renderDrawWidget->setDrawFrameRect(m_drawFrameRect);
       
   744     }
       
   745 
       
   746     QRect scaleToAspect(QRect srcRect, int w, int h)
       
   747     {
       
   748         int width = srcRect.width();
       
   749         int height = srcRect.width() * (float(h) / float(w));
       
   750         if (height > srcRect.height()){
       
   751             height = srcRect.height();
       
   752             width = srcRect.height() * (float(w) / float(h));
       
   753         }
       
   754         return QRect(0, 0, width, height);
       
   755     }
       
   756 };
       
   757 
       
   758 /////////////////////////////////////////////////////////////////////////////////////////
       
   759 
       
   760 VideoWidget::VideoWidget(QObject *parent) : MediaNode(VideoSink, parent)
       
   761 {
       
   762     m_videoRenderWidget = new VideoRenderWidget();
       
   763 }
       
   764 
       
   765 VideoWidget::~VideoWidget()
       
   766 {
       
   767     delete m_videoRenderWidget;
       
   768 }
       
   769 
       
   770 QWidget *VideoWidget::widget()
       
   771 {
       
   772     IMPLEMENTED;
       
   773     return m_videoRenderWidget;
       
   774 }
       
   775 
       
   776 Phonon::VideoWidget::AspectRatio VideoWidget::aspectRatio() const
       
   777 {
       
   778     IMPLEMENTED;
       
   779     return  m_videoRenderWidget->m_aspect;
       
   780 }
       
   781 
       
   782 void VideoWidget::setAspectRatio(Phonon::VideoWidget::AspectRatio aspect)
       
   783 {
       
   784     IMPLEMENTED;
       
   785     m_videoRenderWidget->setAspectRatio(aspect);
       
   786 }
       
   787 
       
   788 Phonon::VideoWidget::ScaleMode VideoWidget::scaleMode() const
       
   789 {
       
   790     IMPLEMENTED;
       
   791     return m_videoRenderWidget->m_scaleMode;
       
   792 }
       
   793 
       
   794 void VideoWidget::setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode)
       
   795 {
       
   796     IMPLEMENTED;
       
   797     m_videoRenderWidget->setScaleMode(scaleMode);
       
   798 }
       
   799 
       
   800 qreal VideoWidget::brightness() const
       
   801 {
       
   802     IMPLEMENTED;
       
   803     return m_videoRenderWidget->m_brightness;
       
   804 }
       
   805 
       
   806 void VideoWidget::setBrightness(qreal value)
       
   807 {
       
   808     IMPLEMENTED;
       
   809     m_videoRenderWidget->m_brightness = value;
       
   810     if (m_owningMediaObject && m_owningMediaObject->state() == Phonon::PausedState)
       
   811         m_videoRenderWidget->updateVideoFrame();
       
   812 }
       
   813 
       
   814 qreal VideoWidget::contrast() const
       
   815 {
       
   816     IMPLEMENTED;
       
   817     return m_videoRenderWidget->m_contrast;
       
   818 }
       
   819 
       
   820 void VideoWidget::setContrast(qreal value)
       
   821 {
       
   822     IMPLEMENTED;
       
   823     m_videoRenderWidget->m_contrast = value;
       
   824     if (m_owningMediaObject && m_owningMediaObject->state() == Phonon::PausedState)
       
   825         m_videoRenderWidget->updateVideoFrame();
       
   826 }
       
   827 
       
   828 qreal VideoWidget::hue() const
       
   829 {
       
   830     IMPLEMENTED;
       
   831     return m_videoRenderWidget->m_hue;
       
   832 }
       
   833 
       
   834 void VideoWidget::setHue(qreal value)
       
   835 {
       
   836     IMPLEMENTED;
       
   837     m_videoRenderWidget->m_hue = value;
       
   838     if (m_owningMediaObject && m_owningMediaObject->state() == Phonon::PausedState)
       
   839         m_videoRenderWidget->updateVideoFrame();
       
   840 }
       
   841 
       
   842 qreal VideoWidget::saturation() const
       
   843 {
       
   844     IMPLEMENTED;
       
   845     return m_videoRenderWidget->m_saturation;
       
   846 }
       
   847 
       
   848 void VideoWidget::setSaturation(qreal value)
       
   849 {
       
   850     IMPLEMENTED;
       
   851     m_videoRenderWidget->m_saturation = value;
       
   852     if (m_owningMediaObject && m_owningMediaObject->state() == Phonon::PausedState)
       
   853         m_videoRenderWidget->updateVideoFrame();
       
   854 }
       
   855 
       
   856 void VideoWidget::mediaNodeEvent(const MediaNodeEvent *event)
       
   857 {
       
   858     switch (event->type()){
       
   859     case MediaNodeEvent::VideoFrameSizeChanged:
       
   860         m_videoRenderWidget->setMovieRect(*static_cast<QRect *>(event->data()));
       
   861         break;
       
   862 	case MediaNodeEvent::VideoOutputCountChanged:
       
   863 	     m_videoRenderWidget->updateVideoOutputCount(*static_cast<int *>(event->data()));
       
   864 	     break;
       
   865 	case MediaNodeEvent::MediaPlaying:
       
   866 	     m_videoRenderWidget->setMovieIsPaused(!(*static_cast<bool *>(event->data())));
       
   867 	     break;
       
   868 	default:
       
   869         break;
       
   870     }
       
   871 }
       
   872 
       
   873 void VideoWidget::updateVideo(VideoFrame &frame){
       
   874 	PhononAutoReleasePool pool;
       
   875     m_videoRenderWidget->setVideoFrame(frame);
       
   876     MediaNode::updateVideo(frame);
       
   877 }
       
   878 
       
   879 }} // namespace Phonon::QT7
       
   880 
       
   881 QT_END_NAMESPACE
       
   882 
       
   883 #include "moc_videowidget.cpp"