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