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 #include <tools/prewin.h> 29 #if defined _MSC_VER 30 #pragma warning(push, 1) 31 #pragma warning(disable: 4917) 32 #endif 33 #include <windows.h> 34 #include <objbase.h> 35 #include <strmif.h> 36 #include <control.h> 37 #include <uuids.h> 38 #include <evcode.h> 39 #if defined _MSC_VER 40 #pragma warning(pop) 41 #endif 42 #include <tools/postwin.h> 43 44 #include "player.hxx" 45 #include "framegrabber.hxx" 46 #include "window.hxx" 47 48 #define AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Player_DirectX" 49 #define AVMEDIA_WIN_PLAYER_SERVICENAME "com.sun.star.media.Player_DirectX" 50 51 using namespace ::com::sun::star; 52 53 namespace avmedia { namespace win { 54 55 LRESULT CALLBACK MediaPlayerWndProc_2( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nPar2 ) 56 { 57 Player* pPlayer = (Player*) ::GetWindowLong( hWnd, 0 ); 58 bool bProcessed = true; 59 60 if( pPlayer ) 61 { 62 switch( nMsg ) 63 { 64 case( WM_GRAPHNOTIFY ): 65 pPlayer->processEvent(); 66 break; 67 default: 68 bProcessed = false; 69 break; 70 } 71 } 72 else 73 bProcessed = false; 74 75 return( bProcessed ? 0 : DefWindowProc( hWnd, nMsg, nPar1, nPar2 ) ); 76 } 77 78 79 bool isWindowsVistaOrHigher() 80 { 81 // POST: return true if we are at least on Windows Vista 82 OSVERSIONINFO osvi; 83 ZeroMemory(&osvi, sizeof(osvi)); 84 osvi.dwOSVersionInfoSize = sizeof(osvi); 85 GetVersionEx(&osvi); 86 return osvi.dwMajorVersion >= 6; 87 } 88 89 // ---------------- 90 // - Player - 91 // ---------------- 92 93 Player::Player( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) : 94 Player_BASE(m_aMutex), 95 mxMgr( rxMgr ), 96 mpGB( NULL ), 97 mpOMF( NULL ), 98 mpMC( NULL ), 99 mpME( NULL ), 100 mpMS( NULL ), 101 mpMP( NULL ), 102 mpBA( NULL ), 103 mpBV( NULL ), 104 mpVW( NULL ), 105 mpEV( NULL ), 106 mnUnmutedVolume( 0 ), 107 mnFrameWnd( 0 ), 108 mbMuted( false ), 109 mbLooping( false ), 110 mbAddWindow(sal_True) 111 { 112 ::CoInitialize( NULL ); 113 } 114 115 // ------------------------------------------------------------------------------ 116 117 Player::~Player() 118 { 119 if( mnFrameWnd ) 120 ::DestroyWindow( (HWND) mnFrameWnd ); 121 122 ::CoUninitialize(); 123 } 124 125 // ------------------------------------------------------------------------------ 126 127 void SAL_CALL Player::disposing() 128 { 129 ::osl::MutexGuard aGuard(m_aMutex); 130 stop(); 131 if( mpBA ) 132 mpBA->Release(); 133 134 if( mpBV ) 135 mpBV->Release(); 136 137 if( mpVW ) 138 mpVW->Release(); 139 140 if( mpMP ) 141 mpMP->Release(); 142 143 if( mpMS ) 144 mpMS->Release(); 145 146 if( mpME ) 147 { 148 mpME->SetNotifyWindow( 0, WM_GRAPHNOTIFY, 0); 149 mpME->Release(); 150 } 151 152 153 if( mpMC ) 154 mpMC->Release(); 155 156 if( mpEV ) 157 mpEV->Release(); 158 159 if( mpOMF ) 160 mpOMF->Release(); 161 162 if( mpGB ) 163 mpGB->Release(); 164 } 165 // ------------------------------------------------------------------------------ 166 bool Player::create( const ::rtl::OUString& rURL ) 167 { 168 HRESULT hR; 169 bool bRet = false; 170 171 if( SUCCEEDED( hR = CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**) &mpGB ) ) ) 172 { 173 // Don't use the overlay mixer on Windows Vista 174 // It disables the desktop composition as soon as RenderFile is called 175 // also causes some other problems: video rendering is not reliable 176 if( !isWindowsVistaOrHigher() && SUCCEEDED( CoCreateInstance( CLSID_OverlayMixer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**) &mpOMF ) ) ) 177 { 178 mpGB->AddFilter( mpOMF, L"com_sun_star_media_OverlayMixerFilter" ); 179 180 if( !SUCCEEDED( mpOMF->QueryInterface( IID_IDDrawExclModeVideo, (void**) &mpEV ) ) ) 181 mpEV = NULL; 182 } 183 184 if( SUCCEEDED( hR = mpGB->RenderFile( reinterpret_cast<LPCWSTR>(rURL.getStr()), NULL ) ) && 185 SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaControl, (void**) &mpMC ) ) && 186 SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaEventEx, (void**) &mpME ) ) && 187 SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaSeeking, (void**) &mpMS ) ) && 188 SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaPosition, (void**) &mpMP ) ) ) 189 { 190 // Video interfaces 191 mpGB->QueryInterface( IID_IVideoWindow, (void**) &mpVW ); 192 mpGB->QueryInterface( IID_IBasicVideo, (void**) &mpBV ); 193 194 // Audio interface 195 mpGB->QueryInterface( IID_IBasicAudio, (void**) &mpBA ); 196 197 if( mpBA ) 198 mpBA->put_Volume( mnUnmutedVolume ); 199 200 bRet = true; 201 } 202 } 203 204 if( bRet ) 205 maURL = rURL; 206 else 207 maURL = ::rtl::OUString(); 208 209 return bRet; 210 } 211 212 // ------------------------------------------------------------------------------ 213 214 const IVideoWindow* Player::getVideoWindow() const 215 { 216 return mpVW; 217 } 218 219 // ------------------------------------------------------------------------------ 220 221 void Player::setNotifyWnd( int nNotifyWnd ) 222 { 223 mbAddWindow = sal_False; 224 if( mpME ) 225 mpME->SetNotifyWindow( (OAHWND) nNotifyWnd, WM_GRAPHNOTIFY, reinterpret_cast< LONG_PTR>( this ) ); 226 } 227 228 // ------------------------------------------------------------------------------ 229 230 void Player::setDDrawParams( IDirectDraw* pDDraw, IDirectDrawSurface* pDDrawSurface ) 231 { 232 if( mpEV && pDDraw && pDDrawSurface ) 233 { 234 mpEV->SetDDrawObject( pDDraw ); 235 mpEV->SetDDrawSurface( pDDrawSurface ); 236 } 237 } 238 239 // ------------------------------------------------------------------------------ 240 241 long Player::processEvent() 242 { 243 long nCode, nParam1, nParam2; 244 245 while( mpME && SUCCEEDED( mpME->GetEvent( &nCode, &nParam1, &nParam2, 0 ) ) ) 246 { 247 if( EC_COMPLETE == nCode ) 248 { 249 if( mbLooping ) 250 { 251 setMediaTime( 0.0 ); 252 start(); 253 } 254 else 255 { 256 setMediaTime( getDuration() ); 257 stop(); 258 } 259 } 260 261 mpME->FreeEventParams( nCode, nParam1, nParam2 ); 262 } 263 264 return 0; 265 } 266 267 // ------------------------------------------------------------------------------ 268 269 void SAL_CALL Player::start( ) 270 throw (uno::RuntimeException) 271 { 272 ::osl::MutexGuard aGuard(m_aMutex); 273 if( mpMC ) 274 { 275 if ( mbAddWindow ) 276 { 277 static WNDCLASS* mpWndClass = NULL; 278 if ( !mpWndClass ) 279 { 280 mpWndClass = new WNDCLASS; 281 282 memset( mpWndClass, 0, sizeof( *mpWndClass ) ); 283 mpWndClass->hInstance = GetModuleHandle( NULL ); 284 mpWndClass->cbWndExtra = sizeof( DWORD ); 285 mpWndClass->lpfnWndProc = MediaPlayerWndProc_2; 286 mpWndClass->lpszClassName = "com_sun_star_media_Sound_Player"; 287 mpWndClass->hbrBackground = (HBRUSH) ::GetStockObject( BLACK_BRUSH ); 288 mpWndClass->hCursor = ::LoadCursor( NULL, IDC_ARROW ); 289 290 ::RegisterClass( mpWndClass ); 291 } 292 if ( !mnFrameWnd ) 293 { 294 mnFrameWnd = (int) ::CreateWindow( mpWndClass->lpszClassName, NULL, 295 0, 296 0, 0, 0, 0, 297 (HWND) NULL, NULL, mpWndClass->hInstance, 0 ); 298 if ( mnFrameWnd ) 299 { 300 ::ShowWindow((HWND) mnFrameWnd, SW_HIDE); 301 ::SetWindowLong( (HWND) mnFrameWnd, 0, (DWORD) this ); 302 // mpVW->put_Owner( (OAHWND) mnFrameWnd ); 303 setNotifyWnd( mnFrameWnd ); 304 } 305 } 306 } 307 308 mpMC->Run(); 309 } 310 } 311 312 // ------------------------------------------------------------------------------ 313 314 void SAL_CALL Player::stop( ) 315 throw (uno::RuntimeException) 316 { 317 ::osl::MutexGuard aGuard(m_aMutex); 318 319 if( mpMC ) 320 mpMC->Stop(); 321 } 322 323 // ------------------------------------------------------------------------------ 324 325 sal_Bool SAL_CALL Player::isPlaying() 326 throw (uno::RuntimeException) 327 { 328 ::osl::MutexGuard aGuard(m_aMutex); 329 330 OAFilterState eFilterState; 331 bool bRet = false; 332 333 if( mpMC && SUCCEEDED( mpMC->GetState( 10, &eFilterState ) ) ) 334 bRet = ( State_Running == eFilterState ); 335 336 return bRet; 337 } 338 339 // ------------------------------------------------------------------------------ 340 341 double SAL_CALL Player::getDuration( ) 342 throw (uno::RuntimeException) 343 { 344 ::osl::MutexGuard aGuard(m_aMutex); 345 346 REFTIME aRefTime( 0.0 ); 347 348 if( mpMP ) 349 mpMP->get_Duration( &aRefTime ); 350 351 return aRefTime; 352 } 353 354 // ------------------------------------------------------------------------------ 355 356 void SAL_CALL Player::setMediaTime( double fTime ) 357 throw (uno::RuntimeException) 358 { 359 ::osl::MutexGuard aGuard(m_aMutex); 360 361 if( mpMP ) 362 { 363 const bool bPlaying = isPlaying(); 364 365 mpMP->put_CurrentPosition( fTime ); 366 367 if( !bPlaying && mpMC ) 368 mpMC->StopWhenReady(); 369 } 370 } 371 372 // ------------------------------------------------------------------------------ 373 374 double SAL_CALL Player::getMediaTime( ) 375 throw (uno::RuntimeException) 376 { 377 ::osl::MutexGuard aGuard(m_aMutex); 378 379 REFTIME aRefTime( 0.0 ); 380 381 if( mpMP ) 382 mpMP->get_CurrentPosition( &aRefTime ); 383 384 return aRefTime; 385 } 386 387 // ------------------------------------------------------------------------------ 388 389 void SAL_CALL Player::setStopTime( double fTime ) 390 throw (uno::RuntimeException) 391 { 392 ::osl::MutexGuard aGuard(m_aMutex); 393 394 if( mpMP ) 395 mpMP->put_StopTime( fTime ); 396 } 397 398 // ------------------------------------------------------------------------------ 399 400 double SAL_CALL Player::getStopTime( ) 401 throw (uno::RuntimeException) 402 { 403 ::osl::MutexGuard aGuard(m_aMutex); 404 405 REFTIME aRefTime( 0.0 ); 406 407 if( mpMP ) 408 mpMP->get_StopTime( &aRefTime ); 409 410 return aRefTime; 411 } 412 413 // ------------------------------------------------------------------------------ 414 415 void SAL_CALL Player::setRate( double fRate ) 416 throw (uno::RuntimeException) 417 { 418 ::osl::MutexGuard aGuard(m_aMutex); 419 420 if( mpMP ) 421 mpMP->put_Rate( fRate ); 422 } 423 424 // ------------------------------------------------------------------------------ 425 426 double SAL_CALL Player::getRate( ) 427 throw (uno::RuntimeException) 428 { 429 ::osl::MutexGuard aGuard(m_aMutex); 430 431 double fRet( 0.0 ); 432 433 if( mpMP ) 434 mpMP->get_Rate( &fRet ); 435 436 return fRet; 437 } 438 439 // ------------------------------------------------------------------------------ 440 441 void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet ) 442 throw (uno::RuntimeException) 443 { 444 ::osl::MutexGuard aGuard(m_aMutex); 445 446 mbLooping = bSet; 447 } 448 449 // ------------------------------------------------------------------------------ 450 451 sal_Bool SAL_CALL Player::isPlaybackLoop( ) 452 throw (uno::RuntimeException) 453 { 454 ::osl::MutexGuard aGuard(m_aMutex); 455 456 return mbLooping; 457 } 458 459 // ------------------------------------------------------------------------------ 460 461 void SAL_CALL Player::setMute( sal_Bool bSet ) 462 throw (uno::RuntimeException) 463 { 464 ::osl::MutexGuard aGuard(m_aMutex); 465 466 if( mpBA && ( mbMuted != bSet ) ) 467 { 468 mbMuted = bSet; 469 mpBA->put_Volume( mbMuted ? -10000 : mnUnmutedVolume ); 470 } 471 } 472 473 // ------------------------------------------------------------------------------ 474 475 sal_Bool SAL_CALL Player::isMute( ) 476 throw (uno::RuntimeException) 477 { 478 ::osl::MutexGuard aGuard(m_aMutex); 479 480 return mbMuted; 481 } 482 483 // ------------------------------------------------------------------------------ 484 485 void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB ) 486 throw (uno::RuntimeException) 487 { 488 ::osl::MutexGuard aGuard(m_aMutex); 489 490 mnUnmutedVolume = static_cast< long >( nVolumeDB ) * 100; 491 492 if( !mbMuted && mpBA ) 493 mpBA->put_Volume( mnUnmutedVolume ); 494 } 495 496 // ------------------------------------------------------------------------------ 497 498 sal_Int16 SAL_CALL Player::getVolumeDB( ) 499 throw (uno::RuntimeException) 500 { 501 ::osl::MutexGuard aGuard(m_aMutex); 502 503 return( static_cast< sal_Int16 >( mnUnmutedVolume / 100 ) ); 504 } 505 506 // ------------------------------------------------------------------------------ 507 508 awt::Size SAL_CALL Player::getPreferredPlayerWindowSize( ) 509 throw (uno::RuntimeException) 510 { 511 ::osl::MutexGuard aGuard(m_aMutex); 512 513 awt::Size aSize( 0, 0 ); 514 515 if( mpBV ) 516 { 517 long nWidth = 0, nHeight = 0; 518 519 mpBV->GetVideoSize( &nWidth, &nHeight ); 520 aSize.Width = nWidth; 521 aSize.Height = nHeight; 522 } 523 524 return aSize; 525 } 526 527 // ------------------------------------------------------------------------------ 528 529 uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( const uno::Sequence< uno::Any >& aArguments ) 530 throw (uno::RuntimeException) 531 { 532 ::osl::MutexGuard aGuard(m_aMutex); 533 534 uno::Reference< ::media::XPlayerWindow > xRet; 535 awt::Size aSize( getPreferredPlayerWindowSize() ); 536 537 if( mpVW && aSize.Width > 0 && aSize.Height > 0 ) 538 { 539 ::avmedia::win::Window* pWindow = new ::avmedia::win::Window( mxMgr, *this ); 540 541 xRet = pWindow; 542 543 if( !pWindow->create( aArguments ) ) 544 xRet = uno::Reference< ::media::XPlayerWindow >(); 545 } 546 547 return xRet; 548 } 549 550 // ------------------------------------------------------------------------------ 551 552 uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber( ) 553 throw (uno::RuntimeException) 554 { 555 ::osl::MutexGuard aGuard(m_aMutex); 556 557 uno::Reference< media::XFrameGrabber > xRet; 558 559 if( maURL.getLength() > 0 ) 560 { 561 FrameGrabber* pGrabber = new FrameGrabber( mxMgr ); 562 563 xRet = pGrabber; 564 565 if( !pGrabber->create( maURL ) ) 566 xRet.clear(); 567 } 568 569 return xRet; 570 } 571 572 // ------------------------------------------------------------------------------ 573 574 ::rtl::OUString SAL_CALL Player::getImplementationName( ) 575 throw (uno::RuntimeException) 576 { 577 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME ) ); 578 } 579 580 // ------------------------------------------------------------------------------ 581 582 sal_Bool SAL_CALL Player::supportsService( const ::rtl::OUString& ServiceName ) 583 throw (uno::RuntimeException) 584 { 585 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( AVMEDIA_WIN_PLAYER_SERVICENAME ) ); 586 } 587 588 // ------------------------------------------------------------------------------ 589 590 uno::Sequence< ::rtl::OUString > SAL_CALL Player::getSupportedServiceNames( ) 591 throw (uno::RuntimeException) 592 { 593 uno::Sequence< ::rtl::OUString > aRet(1); 594 aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( AVMEDIA_WIN_PLAYER_SERVICENAME ) ); 595 596 return aRet; 597 } 598 599 } // namespace win 600 } // namespace avmedia 601