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< uno::XComponentContext >& rxContext ) : 90 Player_BASE(m_aMutex), 91 mxContext( rxContext ), 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; 240 LONG_PTR nParam1, nParam2; 241 242 while( mpME && SUCCEEDED( mpME->GetEvent( &nCode, &nParam1, &nParam2, 0 ) ) ) 243 { 244 if( EC_COMPLETE == nCode ) 245 { 246 if( mbLooping ) 247 { 248 setMediaTime( 0.0 ); 249 start(); 250 } 251 else 252 { 253 setMediaTime( getDuration() ); 254 stop(); 255 } 256 } 257 258 mpME->FreeEventParams( nCode, nParam1, nParam2 ); 259 } 260 261 return 0; 262 } 263 264 // ------------------------------------------------------------------------------ 265 266 void SAL_CALL Player::start( ) 267 throw (uno::RuntimeException) 268 { 269 ::osl::MutexGuard aGuard(m_aMutex); 270 if( mpMC ) 271 { 272 if ( mbAddWindow ) 273 { 274 static WNDCLASS* mpWndClass = NULL; 275 if ( !mpWndClass ) 276 { 277 mpWndClass = new WNDCLASS; 278 279 memset( mpWndClass, 0, sizeof( *mpWndClass ) ); 280 mpWndClass->hInstance = GetModuleHandle( NULL ); 281 mpWndClass->cbWndExtra = sizeof( DWORD ); 282 mpWndClass->lpfnWndProc = MediaPlayerWndProc_2; 283 mpWndClass->lpszClassName = "com_sun_star_media_Sound_Player"; 284 mpWndClass->hbrBackground = (HBRUSH) ::GetStockObject( BLACK_BRUSH ); 285 mpWndClass->hCursor = ::LoadCursor( NULL, IDC_ARROW ); 286 287 ::RegisterClass( mpWndClass ); 288 } 289 if ( !mnFrameWnd ) 290 { 291 mnFrameWnd = (int) ::CreateWindow( mpWndClass->lpszClassName, NULL, 292 0, 293 0, 0, 0, 0, 294 (HWND) NULL, NULL, mpWndClass->hInstance, 0 ); 295 if ( mnFrameWnd ) 296 { 297 ::ShowWindow((HWND) mnFrameWnd, SW_HIDE); 298 ::SetWindowLong( (HWND) mnFrameWnd, 0, (DWORD) this ); 299 // mpVW->put_Owner( (OAHWND) mnFrameWnd ); 300 setNotifyWnd( mnFrameWnd ); 301 } 302 } 303 } 304 305 mpMC->Run(); 306 } 307 } 308 309 // ------------------------------------------------------------------------------ 310 311 void SAL_CALL Player::stop( ) 312 throw (uno::RuntimeException) 313 { 314 ::osl::MutexGuard aGuard(m_aMutex); 315 316 if( mpMC ) 317 mpMC->Stop(); 318 } 319 320 // ------------------------------------------------------------------------------ 321 322 sal_Bool SAL_CALL Player::isPlaying() 323 throw (uno::RuntimeException) 324 { 325 ::osl::MutexGuard aGuard(m_aMutex); 326 327 OAFilterState eFilterState; 328 bool bRet = false; 329 330 if( mpMC && SUCCEEDED( mpMC->GetState( 10, &eFilterState ) ) ) 331 bRet = ( State_Running == eFilterState ); 332 333 return bRet; 334 } 335 336 // ------------------------------------------------------------------------------ 337 338 double SAL_CALL Player::getDuration( ) 339 throw (uno::RuntimeException) 340 { 341 ::osl::MutexGuard aGuard(m_aMutex); 342 343 REFTIME aRefTime( 0.0 ); 344 345 if( mpMP ) 346 mpMP->get_Duration( &aRefTime ); 347 348 return aRefTime; 349 } 350 351 // ------------------------------------------------------------------------------ 352 353 void SAL_CALL Player::setMediaTime( double fTime ) 354 throw (uno::RuntimeException) 355 { 356 ::osl::MutexGuard aGuard(m_aMutex); 357 358 if( mpMP ) 359 { 360 const bool bPlaying = isPlaying(); 361 362 mpMP->put_CurrentPosition( fTime ); 363 364 if( !bPlaying && mpMC ) 365 mpMC->StopWhenReady(); 366 } 367 } 368 369 // ------------------------------------------------------------------------------ 370 371 double SAL_CALL Player::getMediaTime( ) 372 throw (uno::RuntimeException) 373 { 374 ::osl::MutexGuard aGuard(m_aMutex); 375 376 REFTIME aRefTime( 0.0 ); 377 378 if( mpMP ) 379 mpMP->get_CurrentPosition( &aRefTime ); 380 381 return aRefTime; 382 } 383 384 // ------------------------------------------------------------------------------ 385 386 void SAL_CALL Player::setStopTime( double fTime ) 387 throw (uno::RuntimeException) 388 { 389 ::osl::MutexGuard aGuard(m_aMutex); 390 391 if( mpMP ) 392 mpMP->put_StopTime( fTime ); 393 } 394 395 // ------------------------------------------------------------------------------ 396 397 double SAL_CALL Player::getStopTime( ) 398 throw (uno::RuntimeException) 399 { 400 ::osl::MutexGuard aGuard(m_aMutex); 401 402 REFTIME aRefTime( 0.0 ); 403 404 if( mpMP ) 405 mpMP->get_StopTime( &aRefTime ); 406 407 return aRefTime; 408 } 409 410 // ------------------------------------------------------------------------------ 411 412 void SAL_CALL Player::setRate( double fRate ) 413 throw (uno::RuntimeException) 414 { 415 ::osl::MutexGuard aGuard(m_aMutex); 416 417 if( mpMP ) 418 mpMP->put_Rate( fRate ); 419 } 420 421 // ------------------------------------------------------------------------------ 422 423 double SAL_CALL Player::getRate( ) 424 throw (uno::RuntimeException) 425 { 426 ::osl::MutexGuard aGuard(m_aMutex); 427 428 double fRet( 0.0 ); 429 430 if( mpMP ) 431 mpMP->get_Rate( &fRet ); 432 433 return fRet; 434 } 435 436 // ------------------------------------------------------------------------------ 437 438 void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet ) 439 throw (uno::RuntimeException) 440 { 441 ::osl::MutexGuard aGuard(m_aMutex); 442 443 mbLooping = bSet; 444 } 445 446 // ------------------------------------------------------------------------------ 447 448 sal_Bool SAL_CALL Player::isPlaybackLoop( ) 449 throw (uno::RuntimeException) 450 { 451 ::osl::MutexGuard aGuard(m_aMutex); 452 453 return mbLooping; 454 } 455 456 // ------------------------------------------------------------------------------ 457 458 void SAL_CALL Player::setMute( sal_Bool bSet ) 459 throw (uno::RuntimeException) 460 { 461 ::osl::MutexGuard aGuard(m_aMutex); 462 463 if( mpBA && ( mbMuted != bSet ) ) 464 { 465 mbMuted = bSet; 466 mpBA->put_Volume( mbMuted ? -10000 : mnUnmutedVolume ); 467 } 468 } 469 470 // ------------------------------------------------------------------------------ 471 472 sal_Bool SAL_CALL Player::isMute( ) 473 throw (uno::RuntimeException) 474 { 475 ::osl::MutexGuard aGuard(m_aMutex); 476 477 return mbMuted; 478 } 479 480 // ------------------------------------------------------------------------------ 481 482 void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB ) 483 throw (uno::RuntimeException) 484 { 485 ::osl::MutexGuard aGuard(m_aMutex); 486 487 mnUnmutedVolume = static_cast< long >( nVolumeDB ) * 100; 488 489 if( !mbMuted && mpBA ) 490 mpBA->put_Volume( mnUnmutedVolume ); 491 } 492 493 // ------------------------------------------------------------------------------ 494 495 sal_Int16 SAL_CALL Player::getVolumeDB( ) 496 throw (uno::RuntimeException) 497 { 498 ::osl::MutexGuard aGuard(m_aMutex); 499 500 return( static_cast< sal_Int16 >( mnUnmutedVolume / 100 ) ); 501 } 502 503 // ------------------------------------------------------------------------------ 504 505 awt::Size SAL_CALL Player::getPreferredPlayerWindowSize( ) 506 throw (uno::RuntimeException) 507 { 508 ::osl::MutexGuard aGuard(m_aMutex); 509 510 awt::Size aSize( 0, 0 ); 511 512 if( mpBV ) 513 { 514 long nWidth = 0, nHeight = 0; 515 516 mpBV->GetVideoSize( &nWidth, &nHeight ); 517 aSize.Width = nWidth; 518 aSize.Height = nHeight; 519 } 520 521 return aSize; 522 } 523 524 // ------------------------------------------------------------------------------ 525 526 uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( const uno::Sequence< uno::Any >& aArguments ) 527 throw (uno::RuntimeException) 528 { 529 ::osl::MutexGuard aGuard(m_aMutex); 530 531 uno::Reference< ::media::XPlayerWindow > xRet; 532 awt::Size aSize( getPreferredPlayerWindowSize() ); 533 534 if( mpVW && aSize.Width > 0 && aSize.Height > 0 ) 535 { 536 ::avmedia::win::Window* pWindow = new ::avmedia::win::Window( mxContext, *this ); 537 538 xRet = pWindow; 539 540 if( !pWindow->create( aArguments ) ) 541 xRet = uno::Reference< ::media::XPlayerWindow >(); 542 } 543 544 return xRet; 545 } 546 547 // ------------------------------------------------------------------------------ 548 549 uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber( ) 550 throw (uno::RuntimeException) 551 { 552 ::osl::MutexGuard aGuard(m_aMutex); 553 554 uno::Reference< media::XFrameGrabber > xRet; 555 556 if( !maURL.isEmpty() ) 557 { 558 FrameGrabber* pGrabber = new FrameGrabber( mxContext ); 559 560 xRet = pGrabber; 561 562 if( !pGrabber->create( maURL ) ) 563 xRet.clear(); 564 } 565 566 return xRet; 567 } 568 569 // ------------------------------------------------------------------------------ 570 571 ::rtl::OUString SAL_CALL Player::getImplementationName( ) 572 throw (uno::RuntimeException) 573 { 574 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME ) ); 575 } 576 577 // ------------------------------------------------------------------------------ 578 579 sal_Bool SAL_CALL Player::supportsService( const ::rtl::OUString& ServiceName ) 580 throw (uno::RuntimeException) 581 { 582 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( AVMEDIA_WIN_PLAYER_SERVICENAME ) ); 583 } 584 585 // ------------------------------------------------------------------------------ 586 587 uno::Sequence< ::rtl::OUString > SAL_CALL Player::getSupportedServiceNames( ) 588 throw (uno::RuntimeException) 589 { 590 uno::Sequence< ::rtl::OUString > aRet(1); 591 aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( AVMEDIA_WIN_PLAYER_SERVICENAME ) ); 592 593 return aRet; 594 } 595 596 } // namespace win 597 } // namespace avmedia 598