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 { 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 { 312 ::osl::MutexGuard aGuard(m_aMutex); 313 314 if( mpMC ) 315 mpMC->Stop(); 316 } 317 318 // ------------------------------------------------------------------------------ 319 320 sal_Bool SAL_CALL Player::isPlaying() 321 { 322 ::osl::MutexGuard aGuard(m_aMutex); 323 324 OAFilterState eFilterState; 325 bool bRet = false; 326 327 if( mpMC && SUCCEEDED( mpMC->GetState( 10, &eFilterState ) ) ) 328 bRet = ( State_Running == eFilterState ); 329 330 return bRet; 331 } 332 333 // ------------------------------------------------------------------------------ 334 335 double SAL_CALL Player::getDuration( ) 336 { 337 ::osl::MutexGuard aGuard(m_aMutex); 338 339 REFTIME aRefTime( 0.0 ); 340 341 if( mpMP ) 342 mpMP->get_Duration( &aRefTime ); 343 344 return aRefTime; 345 } 346 347 // ------------------------------------------------------------------------------ 348 349 void SAL_CALL Player::setMediaTime( double fTime ) 350 { 351 ::osl::MutexGuard aGuard(m_aMutex); 352 353 if( mpMP ) 354 { 355 const bool bPlaying = isPlaying(); 356 357 mpMP->put_CurrentPosition( fTime ); 358 359 if( !bPlaying && mpMC ) 360 mpMC->StopWhenReady(); 361 } 362 } 363 364 // ------------------------------------------------------------------------------ 365 366 double SAL_CALL Player::getMediaTime( ) 367 { 368 ::osl::MutexGuard aGuard(m_aMutex); 369 370 REFTIME aRefTime( 0.0 ); 371 372 if( mpMP ) 373 mpMP->get_CurrentPosition( &aRefTime ); 374 375 return aRefTime; 376 } 377 378 // ------------------------------------------------------------------------------ 379 380 void SAL_CALL Player::setStopTime( double fTime ) 381 { 382 ::osl::MutexGuard aGuard(m_aMutex); 383 384 if( mpMP ) 385 mpMP->put_StopTime( fTime ); 386 } 387 388 // ------------------------------------------------------------------------------ 389 390 double SAL_CALL Player::getStopTime( ) 391 { 392 ::osl::MutexGuard aGuard(m_aMutex); 393 394 REFTIME aRefTime( 0.0 ); 395 396 if( mpMP ) 397 mpMP->get_StopTime( &aRefTime ); 398 399 return aRefTime; 400 } 401 402 // ------------------------------------------------------------------------------ 403 404 void SAL_CALL Player::setRate( double fRate ) 405 { 406 ::osl::MutexGuard aGuard(m_aMutex); 407 408 if( mpMP ) 409 mpMP->put_Rate( fRate ); 410 } 411 412 // ------------------------------------------------------------------------------ 413 414 double SAL_CALL Player::getRate( ) 415 { 416 ::osl::MutexGuard aGuard(m_aMutex); 417 418 double fRet( 0.0 ); 419 420 if( mpMP ) 421 mpMP->get_Rate( &fRet ); 422 423 return fRet; 424 } 425 426 // ------------------------------------------------------------------------------ 427 428 void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet ) 429 { 430 ::osl::MutexGuard aGuard(m_aMutex); 431 432 mbLooping = bSet; 433 } 434 435 // ------------------------------------------------------------------------------ 436 437 sal_Bool SAL_CALL Player::isPlaybackLoop( ) 438 { 439 ::osl::MutexGuard aGuard(m_aMutex); 440 441 return mbLooping; 442 } 443 444 // ------------------------------------------------------------------------------ 445 446 void SAL_CALL Player::setMute( sal_Bool bSet ) 447 { 448 ::osl::MutexGuard aGuard(m_aMutex); 449 450 if( mpBA && ( mbMuted != bSet ) ) 451 { 452 mbMuted = bSet; 453 mpBA->put_Volume( mbMuted ? -10000 : mnUnmutedVolume ); 454 } 455 } 456 457 // ------------------------------------------------------------------------------ 458 459 sal_Bool SAL_CALL Player::isMute( ) 460 { 461 ::osl::MutexGuard aGuard(m_aMutex); 462 463 return mbMuted; 464 } 465 466 // ------------------------------------------------------------------------------ 467 468 void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB ) 469 { 470 ::osl::MutexGuard aGuard(m_aMutex); 471 472 mnUnmutedVolume = static_cast< long >( nVolumeDB ) * 100; 473 474 if( !mbMuted && mpBA ) 475 mpBA->put_Volume( mnUnmutedVolume ); 476 } 477 478 // ------------------------------------------------------------------------------ 479 480 sal_Int16 SAL_CALL Player::getVolumeDB( ) 481 { 482 ::osl::MutexGuard aGuard(m_aMutex); 483 484 return( static_cast< sal_Int16 >( mnUnmutedVolume / 100 ) ); 485 } 486 487 // ------------------------------------------------------------------------------ 488 489 awt::Size SAL_CALL Player::getPreferredPlayerWindowSize( ) 490 { 491 ::osl::MutexGuard aGuard(m_aMutex); 492 493 awt::Size aSize( 0, 0 ); 494 495 if( mpBV ) 496 { 497 long nWidth = 0, nHeight = 0; 498 499 mpBV->GetVideoSize( &nWidth, &nHeight ); 500 aSize.Width = nWidth; 501 aSize.Height = nHeight; 502 } 503 504 return aSize; 505 } 506 507 // ------------------------------------------------------------------------------ 508 509 uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( const uno::Sequence< uno::Any >& aArguments ) 510 { 511 ::osl::MutexGuard aGuard(m_aMutex); 512 513 uno::Reference< ::media::XPlayerWindow > xRet; 514 awt::Size aSize( getPreferredPlayerWindowSize() ); 515 516 if( mpVW && aSize.Width > 0 && aSize.Height > 0 ) 517 { 518 ::avmedia::win::Window* pWindow = new ::avmedia::win::Window( mxContext, *this ); 519 520 xRet = pWindow; 521 522 if( !pWindow->create( aArguments ) ) 523 xRet = uno::Reference< ::media::XPlayerWindow >(); 524 } 525 526 return xRet; 527 } 528 529 // ------------------------------------------------------------------------------ 530 531 uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber( ) 532 { 533 ::osl::MutexGuard aGuard(m_aMutex); 534 535 uno::Reference< media::XFrameGrabber > xRet; 536 537 if( !maURL.isEmpty() ) 538 { 539 FrameGrabber* pGrabber = new FrameGrabber( mxContext ); 540 541 xRet = pGrabber; 542 543 if( !pGrabber->create( maURL ) ) 544 xRet.clear(); 545 } 546 547 return xRet; 548 } 549 550 // ------------------------------------------------------------------------------ 551 552 ::rtl::OUString SAL_CALL Player::getImplementationName( ) 553 { 554 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME ) ); 555 } 556 557 // ------------------------------------------------------------------------------ 558 559 sal_Bool SAL_CALL Player::supportsService( const ::rtl::OUString& ServiceName ) 560 { 561 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( AVMEDIA_WIN_PLAYER_SERVICENAME ) ); 562 } 563 564 // ------------------------------------------------------------------------------ 565 566 uno::Sequence< ::rtl::OUString > SAL_CALL Player::getSupportedServiceNames( ) 567 { 568 uno::Sequence< ::rtl::OUString > aRet(1); 569 aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( AVMEDIA_WIN_PLAYER_SERVICENAME ) ); 570 571 return aRet; 572 } 573 574 } // namespace win 575 } // namespace avmedia 576