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 206VIDEO_TRANSPARENT(mouseDown); 207VIDEO_TRANSPARENT(mouseDragged); 208VIDEO_TRANSPARENT(mouseUp); 209VIDEO_TRANSPARENT(mouseMoved); 210VIDEO_TRANSPARENT(mouseEntered); 211VIDEO_TRANSPARENT(mouseExited); 212VIDEO_TRANSPARENT(rightMouseDown); 213VIDEO_TRANSPARENT(rightMouseDragged); 214VIDEO_TRANSPARENT(rightMouseUp); 215VIDEO_TRANSPARENT(otherMouseDown); 216VIDEO_TRANSPARENT(otherMouseDragged); 217VIDEO_TRANSPARENT(otherMouseUp); 218VIDEO_TRANSPARENT(keyDown); 219VIDEO_TRANSPARENT(keyUp); 220VIDEO_TRANSPARENT(scrollWheel) 221 222@end 223 224#endif // QT_MAC_USE_COCOA 225 226///////////////////////////////////////////////////////////////////////////////////////// 227 228QT_BEGIN_NAMESPACE 229 230namespace Phonon 231{ 232namespace QT7 233{ 234 235class IVideoRenderDrawWidget 236{ 237public: 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 247QGLWidget *PhononSharedQGLWidget(){ 248 static QGLWidget *glWidget = 0; 249 if (!glWidget) 250 glWidget = new QGLWidget(); 251 return glWidget; 252} 253 254///////////////////////////////////////////////////////////////////////////////////////// 255 256class RenderOpenGL : public QGLWidget, public IVideoRenderDrawWidget 257{ 258public: 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 307class RenderQTMovieView : public QWidget, public IVideoRenderDrawWidget 308{ 309public: 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 419class RenderQTMovieLayer : public QWidget, public IVideoRenderDrawWidget 420{ 421public: 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 466class VideoRenderWidget : public QWidget 467{ 468public: 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 762VideoWidget::VideoWidget(QObject *parent) : MediaNode(VideoSink, parent) 763{ 764 m_videoRenderWidget = new VideoRenderWidget(); 765} 766 767VideoWidget::~VideoWidget() 768{ 769 delete m_videoRenderWidget; 770} 771 772QWidget *VideoWidget::widget() 773{ 774 IMPLEMENTED; 775 return m_videoRenderWidget; 776} 777 778Phonon::VideoWidget::AspectRatio VideoWidget::aspectRatio() const 779{ 780 IMPLEMENTED; 781 return m_videoRenderWidget->m_aspect; 782} 783 784void VideoWidget::setAspectRatio(Phonon::VideoWidget::AspectRatio aspect) 785{ 786 IMPLEMENTED; 787 m_videoRenderWidget->setAspectRatio(aspect); 788} 789 790Phonon::VideoWidget::ScaleMode VideoWidget::scaleMode() const 791{ 792 IMPLEMENTED; 793 return m_videoRenderWidget->m_scaleMode; 794} 795 796void VideoWidget::setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode) 797{ 798 IMPLEMENTED; 799 m_videoRenderWidget->setScaleMode(scaleMode); 800} 801 802qreal VideoWidget::brightness() const 803{ 804 IMPLEMENTED; 805 return m_videoRenderWidget->m_brightness; 806} 807 808void 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 816qreal VideoWidget::contrast() const 817{ 818 IMPLEMENTED; 819 return m_videoRenderWidget->m_contrast; 820} 821 822void 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 830qreal VideoWidget::hue() const 831{ 832 IMPLEMENTED; 833 return m_videoRenderWidget->m_hue; 834} 835 836void 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 844qreal VideoWidget::saturation() const 845{ 846 IMPLEMENTED; 847 return m_videoRenderWidget->m_saturation; 848} 849 850void 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 858void 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 875void VideoWidget::updateVideo(VideoFrame &frame){ 876 PhononAutoReleasePool pool; 877 m_videoRenderWidget->setVideoFrame(frame); 878 MediaNode::updateVideo(frame); 879} 880 881}} // namespace Phonon::QT7 882 883QT_END_NAMESPACE 884 885#include "moc_videowidget.cpp" 886