1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_slideshow.hxx" 30 31 // must be first 32 #include <canvas/debug.hxx> 33 #include <tools/diagnose_ex.h> 34 #include <canvas/verbosetrace.hxx> 35 36 #include <math.h> 37 38 #include <comphelper/anytostring.hxx> 39 #include <cppuhelper/exc_hlp.hxx> 40 41 #include <vcl/window.hxx> 42 #include <vcl/syschild.hxx> 43 #include <vcl/salbtype.hxx> 44 45 #include <basegfx/tools/canvastools.hxx> 46 #include <basegfx/numeric/ftools.hxx> 47 #include <basegfx/polygon/b2dpolygon.hxx> 48 #include <basegfx/point/b2dpoint.hxx> 49 #include <basegfx/matrix/b2dhommatrix.hxx> 50 #include <basegfx/polygon/b2dpolygontools.hxx> 51 #include <basegfx/range/b2irange.hxx> 52 #include <canvas/canvastools.hxx> 53 #include <cppcanvas/vclfactory.hxx> 54 #include <cppcanvas/basegfxfactory.hxx> 55 #include <cppcanvas/basegfxfactory.hxx> 56 #include <avmedia/mediawindow.hxx> 57 58 #include <com/sun/star/media/XManager.hpp> 59 #include <com/sun/star/media/XPlayer.hpp> 60 #include <com/sun/star/media/XPlayerWindow.hpp> 61 #include <com/sun/star/beans/XPropertySet.hpp> 62 #include <com/sun/star/lang/XMultiComponentFactory.hpp> 63 #include <com/sun/star/lang/NoSupportException.hpp> 64 #include <com/sun/star/awt/XWindow.hpp> 65 #include <com/sun/star/rendering/XCanvas.hpp> 66 #include <com/sun/star/lang/XComponent.hdl> 67 68 #include "viewmediashape.hxx" 69 #include "mediashape.hxx" 70 #include "tools.hxx" 71 #include "unoview.hxx" 72 73 using namespace ::com::sun::star; 74 75 namespace slideshow 76 { 77 namespace internal 78 { 79 ViewMediaShape::ViewMediaShape( const ViewLayerSharedPtr& rViewLayer, 80 const uno::Reference< drawing::XShape >& rxShape, 81 const uno::Reference< uno::XComponentContext >& rxContext ) : 82 mpViewLayer( rViewLayer ), 83 mpMediaWindow(), 84 maWindowOffset( 0, 0 ), 85 maBounds(), 86 mxShape( rxShape ), 87 mxPlayer(), 88 mxPlayerWindow(), 89 mxComponentContext( rxContext ), 90 mbIsSoundEnabled(true) 91 { 92 ENSURE_OR_THROW( mxShape.is(), "ViewMediaShape::ViewMediaShape(): Invalid Shape" ); 93 ENSURE_OR_THROW( mpViewLayer, "ViewMediaShape::ViewMediaShape(): Invalid View" ); 94 ENSURE_OR_THROW( mpViewLayer->getCanvas(), "ViewMediaShape::ViewMediaShape(): Invalid ViewLayer canvas" ); 95 ENSURE_OR_THROW( mxComponentContext.is(), "ViewMediaShape::ViewMediaShape(): Invalid component context" ); 96 97 UnoViewSharedPtr pUnoView (::boost::dynamic_pointer_cast<UnoView>(rViewLayer)); 98 if (pUnoView) 99 { 100 mbIsSoundEnabled = pUnoView->isSoundEnabled(); 101 } 102 } 103 104 // --------------------------------------------------------------------- 105 106 ViewMediaShape::~ViewMediaShape() 107 { 108 try 109 { 110 endMedia(); 111 } 112 catch (uno::Exception &) 113 { 114 OSL_ENSURE( false, rtl::OUStringToOString( 115 comphelper::anyToString( 116 cppu::getCaughtException() ), 117 RTL_TEXTENCODING_UTF8 ).getStr() ); 118 } 119 } 120 121 // --------------------------------------------------------------------- 122 123 ViewLayerSharedPtr ViewMediaShape::getViewLayer() const 124 { 125 return mpViewLayer; 126 } 127 128 // --------------------------------------------------------------------- 129 130 bool ViewMediaShape::startMedia() 131 { 132 if( !mxPlayer.is() ) 133 implInitialize( maBounds ); 134 135 if( mxPlayer.is() && ( mxPlayer->getDuration() > 0.0 ) ) 136 mxPlayer->start(); 137 138 return true; 139 } 140 141 // --------------------------------------------------------------------- 142 143 void ViewMediaShape::endMedia() 144 { 145 // shutdown player window 146 if( mxPlayerWindow.is() ) 147 { 148 uno::Reference< lang::XComponent > xComponent( mxPlayerWindow, uno::UNO_QUERY ); 149 150 if( xComponent.is() ) 151 xComponent->dispose(); 152 153 mxPlayerWindow.clear(); 154 } 155 156 mpMediaWindow = ::std::auto_ptr< SystemChildWindow >(); 157 158 // shutdown player 159 if( mxPlayer.is() ) 160 { 161 mxPlayer->stop(); 162 163 uno::Reference< lang::XComponent > xComponent( mxPlayer, uno::UNO_QUERY ); 164 165 if( xComponent.is() ) 166 xComponent->dispose(); 167 168 mxPlayer.clear(); 169 } 170 } 171 172 // --------------------------------------------------------------------- 173 174 void ViewMediaShape::pauseMedia() 175 { 176 if( mxPlayer.is() && ( mxPlayer->getDuration() > 0.0 ) ) 177 mxPlayer->stop(); 178 } 179 180 // --------------------------------------------------------------------- 181 182 void ViewMediaShape::setMediaTime(double fTime) 183 { 184 if( mxPlayer.is() && ( mxPlayer->getDuration() > 0.0 ) ) 185 mxPlayer->setMediaTime(fTime); 186 } 187 188 // --------------------------------------------------------------------- 189 190 bool ViewMediaShape::render( const ::basegfx::B2DRectangle& rBounds ) const 191 { 192 ::cppcanvas::CanvasSharedPtr pCanvas = mpViewLayer->getCanvas();; 193 194 if( !pCanvas ) 195 return false; 196 197 if( !mpMediaWindow.get() && !mxPlayerWindow.is() ) 198 { 199 // fill the shape background with black 200 fillRect( pCanvas, 201 rBounds, 202 0x000000FFU ); 203 } 204 205 return true; 206 } 207 208 bool ViewMediaShape::resize( const ::basegfx::B2DRectangle& rNewBounds ) const 209 { 210 maBounds = rNewBounds; 211 212 ::cppcanvas::CanvasSharedPtr pCanvas = mpViewLayer->getCanvas();; 213 214 if( !pCanvas ) 215 return false; 216 217 if( !mxPlayerWindow.is() ) 218 return true; 219 220 uno::Reference< beans::XPropertySet > xPropSet( pCanvas->getUNOCanvas()->getDevice(), 221 uno::UNO_QUERY ); 222 223 uno::Reference< awt::XWindow > xParentWindow; 224 if( xPropSet.is() && 225 getPropertyValue( xParentWindow, 226 xPropSet, 227 ::rtl::OUString::createFromAscii( "Window" )) ) 228 { 229 const awt::Rectangle aRect( xParentWindow->getPosSize() ); 230 231 maWindowOffset.X = aRect.X; 232 maWindowOffset.Y = aRect.Y; 233 } 234 235 ::basegfx::B2DRange aTmpRange; 236 ::canvas::tools::calcTransformedRectBounds( aTmpRange, 237 rNewBounds, 238 mpViewLayer->getTransformation() ); 239 const ::basegfx::B2IRange& rRangePix( 240 ::basegfx::unotools::b2ISurroundingRangeFromB2DRange( aTmpRange )); 241 242 mxPlayerWindow->setEnable( !rRangePix.isEmpty() ); 243 244 if( rRangePix.isEmpty() ) 245 return true; 246 247 const Point aPosPixel( rRangePix.getMinX() + maWindowOffset.X, 248 rRangePix.getMinY() + maWindowOffset.Y ); 249 const Size aSizePixel( rRangePix.getMaxX() - rRangePix.getMinX(), 250 rRangePix.getMaxY() - rRangePix.getMinY() ); 251 252 if( mpMediaWindow.get() ) 253 { 254 mpMediaWindow->SetPosSizePixel( aPosPixel, aSizePixel ); 255 mxPlayerWindow->setPosSize( 0, 0, 256 aSizePixel.Width(), aSizePixel.Height(), 257 0 ); 258 } 259 else 260 { 261 mxPlayerWindow->setPosSize( aPosPixel.X(), aPosPixel.Y(), 262 aSizePixel.Width(), aSizePixel.Height(), 263 0 ); 264 } 265 266 return true; 267 } 268 269 // --------------------------------------------------------------------- 270 271 bool ViewMediaShape::implInitialize( const ::basegfx::B2DRectangle& rBounds ) 272 { 273 if( !mxPlayer.is() && mxShape.is() ) 274 { 275 ENSURE_OR_RETURN_FALSE( mpViewLayer->getCanvas(), 276 "ViewMediaShape::update(): Invalid layer canvas" ); 277 278 uno::Reference< rendering::XCanvas > xCanvas( mpViewLayer->getCanvas()->getUNOCanvas() ); 279 280 if( xCanvas.is() ) 281 { 282 uno::Reference< beans::XPropertySet > xPropSet; 283 ::rtl::OUString aURL; 284 285 try 286 { 287 xPropSet.set( mxShape, uno::UNO_QUERY ); 288 289 // create Player 290 if( xPropSet.is() && 291 ( xPropSet->getPropertyValue( 292 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaURL" ) ) ) >>=aURL ) ) 293 { 294 implInitializeMediaPlayer( aURL ); 295 } 296 297 // create visible object 298 uno::Sequence< uno::Any > aDeviceParams; 299 300 if( ::canvas::tools::getDeviceInfo( xCanvas, aDeviceParams ).getLength() > 1 ) 301 { 302 ::rtl::OUString aImplName; 303 304 aDeviceParams[ 0 ] >>= aImplName; 305 306 if( aImplName.endsWithIgnoreAsciiCaseAsciiL( 307 RTL_CONSTASCII_STRINGPARAM("VCL") )) 308 { 309 implInitializeVCLBasedPlayerWindow( rBounds, aDeviceParams ); 310 } 311 else if( aImplName.endsWithIgnoreAsciiCaseAsciiL( 312 RTL_CONSTASCII_STRINGPARAM("DX")) || 313 aImplName.endsWithIgnoreAsciiCaseAsciiL( 314 RTL_CONSTASCII_STRINGPARAM("DX9"))) 315 { 316 implInitializeDXBasedPlayerWindow( rBounds, aDeviceParams ); 317 } 318 } 319 320 // set player properties 321 implSetMediaProperties( xPropSet ); 322 } 323 catch( uno::RuntimeException& ) 324 { 325 throw; 326 } 327 catch( uno::Exception& ) 328 { 329 OSL_ENSURE( false, 330 rtl::OUStringToOString( 331 comphelper::anyToString( cppu::getCaughtException() ), 332 RTL_TEXTENCODING_UTF8 ).getStr() ); 333 } 334 } 335 } 336 337 return mxPlayer.is() || mxPlayerWindow.is(); 338 } 339 340 // --------------------------------------------------------------------- 341 342 void ViewMediaShape::implSetMediaProperties( const uno::Reference< beans::XPropertySet >& rxProps ) 343 { 344 if( mxPlayer.is() ) 345 { 346 mxPlayer->setMediaTime( 0.0 ); 347 348 if( rxProps.is() ) 349 { 350 sal_Bool bLoop( false ); 351 getPropertyValue( bLoop, 352 rxProps, 353 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Loop" ))); 354 mxPlayer->setPlaybackLoop( bLoop ); 355 356 sal_Bool bMute( false ); 357 getPropertyValue( bMute, 358 rxProps, 359 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Mute" ))); 360 mxPlayer->setMute( bMute || !mbIsSoundEnabled); 361 362 sal_Int16 nVolumeDB(0); 363 getPropertyValue( nVolumeDB, 364 rxProps, 365 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VolumeDB" ))); 366 mxPlayer->setVolumeDB( nVolumeDB ); 367 368 if( mxPlayerWindow.is() ) 369 { 370 media::ZoomLevel eZoom(media::ZoomLevel_FIT_TO_WINDOW); 371 getPropertyValue( eZoom, 372 rxProps, 373 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Zoom" ))); 374 mxPlayerWindow->setZoomLevel( eZoom ); 375 } 376 } 377 } 378 } 379 380 // --------------------------------------------------------------------- 381 382 void ViewMediaShape::implInitializeMediaPlayer( const ::rtl::OUString& rMediaURL ) 383 { 384 if( !mxPlayer.is() ) 385 { 386 try 387 { 388 if( rMediaURL.getLength() ) 389 { 390 mxPlayer.set( avmedia::MediaWindow::createPlayer( rMediaURL ), 391 uno::UNO_QUERY ); 392 } 393 } 394 catch( uno::RuntimeException& ) 395 { 396 throw; 397 } 398 catch( const uno::Exception& ) 399 { 400 throw lang::NoSupportException( 401 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 402 "No video support for ") ) + rMediaURL, 403 uno::Reference<uno::XInterface>() ); 404 } 405 } 406 } 407 408 // --------------------------------------------------------------------- 409 410 bool ViewMediaShape::implInitializeVCLBasedPlayerWindow( const ::basegfx::B2DRectangle& rBounds, 411 const uno::Sequence< uno::Any >& rVCLDeviceParams) 412 { 413 if( !mpMediaWindow.get() && !rBounds.isEmpty() ) 414 { 415 try 416 { 417 sal_Int64 aVal=0; 418 419 rVCLDeviceParams[ 1 ] >>= aVal; 420 421 Window* pWindow = reinterpret_cast< Window* >( aVal ); 422 423 if( pWindow ) 424 { 425 ::basegfx::B2DRange aTmpRange; 426 ::canvas::tools::calcTransformedRectBounds( aTmpRange, 427 rBounds, 428 mpViewLayer->getTransformation() ); 429 const ::basegfx::B2IRange& rRangePix( 430 ::basegfx::unotools::b2ISurroundingRangeFromB2DRange( aTmpRange )); 431 432 if( !rRangePix.isEmpty() ) 433 { 434 uno::Sequence< uno::Any > aArgs( 3 ); 435 awt::Rectangle aAWTRect( rRangePix.getMinX(), 436 rRangePix.getMinY(), 437 rRangePix.getMaxX() - rRangePix.getMinX(), 438 rRangePix.getMaxY() - rRangePix.getMinY() ); 439 440 mpMediaWindow = ::std::auto_ptr< SystemChildWindow >( new 441 SystemChildWindow( pWindow, WB_CLIPCHILDREN ) ); 442 mpMediaWindow->SetBackground( Color( COL_BLACK ) ); 443 mpMediaWindow->SetPosSizePixel( Point( aAWTRect.X, aAWTRect.Y ), 444 Size( aAWTRect.Width, aAWTRect.Height ) ); 445 mpMediaWindow->Show(); 446 447 if( mxPlayer.is() ) 448 { 449 aArgs[ 0 ] = uno::makeAny( 450 sal::static_int_cast< sal_IntPtr >( mpMediaWindow->GetParentWindowHandle() ) ); 451 452 aAWTRect.X = aAWTRect.Y = 0; 453 aArgs[ 1 ] = uno::makeAny( aAWTRect ); 454 455 aArgs[ 2 ] = uno::makeAny( reinterpret_cast< sal_IntPtr >( mpMediaWindow.get() ) ); 456 457 mxPlayerWindow.set( mxPlayer->createPlayerWindow( aArgs ) ); 458 459 if( mxPlayerWindow.is() ) 460 { 461 mxPlayerWindow->setVisible( true ); 462 mxPlayerWindow->setEnable( true ); 463 } 464 } 465 } 466 } 467 } 468 catch( uno::RuntimeException& ) 469 { 470 throw; 471 } 472 catch( uno::Exception& ) 473 { 474 OSL_ENSURE( false, 475 rtl::OUStringToOString( 476 comphelper::anyToString( cppu::getCaughtException() ), 477 RTL_TEXTENCODING_UTF8 ).getStr() ); 478 } 479 } 480 481 return mxPlayerWindow.is(); 482 } 483 484 // --------------------------------------------------------------------- 485 486 bool ViewMediaShape::implInitializeDXBasedPlayerWindow( const ::basegfx::B2DRectangle& rBounds, 487 const uno::Sequence< uno::Any >& rDXDeviceParams ) 488 { 489 if( !mxPlayerWindow.is() ) 490 { 491 try 492 { 493 if( rDXDeviceParams.getLength() == 2 ) 494 { 495 sal_Int64 aWNDVal=0; 496 497 rDXDeviceParams[ 1 ] >>= aWNDVal; 498 499 if( aWNDVal ) 500 { 501 ::basegfx::B2DRange aTmpRange; 502 ::canvas::tools::calcTransformedRectBounds( aTmpRange, 503 rBounds, 504 mpViewLayer->getTransformation() ); 505 const ::basegfx::B2IRange& rRangePix( 506 ::basegfx::unotools::b2ISurroundingRangeFromB2DRange( aTmpRange )); 507 508 if( !rRangePix.isEmpty() ) 509 { 510 uno::Sequence< uno::Any > aArgs( 2 ); 511 awt::Rectangle aAWTRect( rRangePix.getMinX() + maWindowOffset.X, 512 rRangePix.getMinY() + maWindowOffset.Y, 513 rRangePix.getMaxX() - rRangePix.getMinX(), 514 rRangePix.getMaxY() - rRangePix.getMinY() ); 515 516 if( mxPlayer.is() ) 517 { 518 aArgs[ 0 ] = uno::makeAny( sal::static_int_cast< sal_Int32 >( aWNDVal) ); 519 aArgs[ 1 ] = uno::makeAny( aAWTRect ); 520 521 mxPlayerWindow.set( mxPlayer->createPlayerWindow( aArgs ) ); 522 } 523 } 524 } 525 } 526 } 527 catch( uno::RuntimeException& ) 528 { 529 throw; 530 } 531 catch( uno::Exception& ) 532 { 533 OSL_ENSURE( false, 534 rtl::OUStringToOString( 535 comphelper::anyToString( cppu::getCaughtException() ), 536 RTL_TEXTENCODING_UTF8 ).getStr() ); 537 } 538 } 539 540 return mxPlayerWindow.is(); 541 } 542 } 543 } 544