| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| #include <tools/prewin.h> |
| #if defined _MSC_VER |
| #pragma warning(push, 1) |
| #pragma warning(disable: 4917) |
| #endif |
| #include <windows.h> |
| #include <objbase.h> |
| #include <strmif.h> |
| #include <control.h> |
| #include <uuids.h> |
| #include <evcode.h> |
| #if defined _MSC_VER |
| #pragma warning(pop) |
| #endif |
| #include <tools/postwin.h> |
| |
| #include "player.hxx" |
| #include "framegrabber.hxx" |
| #include "window.hxx" |
| |
| #define AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Player_DirectX" |
| #define AVMEDIA_WIN_PLAYER_SERVICENAME "com.sun.star.media.Player_DirectX" |
| |
| using namespace ::com::sun::star; |
| |
| namespace avmedia { namespace win { |
| |
| LRESULT CALLBACK MediaPlayerWndProc_2( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nPar2 ) |
| { |
| Player* pPlayer = (Player*) ::GetWindowLong( hWnd, 0 ); |
| bool bProcessed = true; |
| |
| if( pPlayer ) |
| { |
| switch( nMsg ) |
| { |
| case( WM_GRAPHNOTIFY ): |
| pPlayer->processEvent(); |
| break; |
| default: |
| bProcessed = false; |
| break; |
| } |
| } |
| else |
| bProcessed = false; |
| |
| return( bProcessed ? 0 : DefWindowProc( hWnd, nMsg, nPar1, nPar2 ) ); |
| } |
| |
| |
| bool isWindowsVistaOrHigher() |
| { |
| // POST: return true if we are at least on Windows Vista |
| OSVERSIONINFO osvi; |
| ZeroMemory(&osvi, sizeof(osvi)); |
| osvi.dwOSVersionInfoSize = sizeof(osvi); |
| GetVersionEx(&osvi); |
| return osvi.dwMajorVersion >= 6; |
| } |
| |
| // ---------------- |
| // - Player - |
| // ---------------- |
| |
| Player::Player( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) : |
| Player_BASE(m_aMutex), |
| mxMgr( rxMgr ), |
| mpGB( NULL ), |
| mpOMF( NULL ), |
| mpMC( NULL ), |
| mpME( NULL ), |
| mpMS( NULL ), |
| mpMP( NULL ), |
| mpBA( NULL ), |
| mpBV( NULL ), |
| mpVW( NULL ), |
| mpEV( NULL ), |
| mnUnmutedVolume( 0 ), |
| mnFrameWnd( 0 ), |
| mbMuted( false ), |
| mbLooping( false ), |
| mbAddWindow(sal_True) |
| { |
| ::CoInitialize( NULL ); |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| Player::~Player() |
| { |
| if( mnFrameWnd ) |
| ::DestroyWindow( (HWND) mnFrameWnd ); |
| |
| ::CoUninitialize(); |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| void SAL_CALL Player::disposing() |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| stop(); |
| if( mpBA ) |
| mpBA->Release(); |
| |
| if( mpBV ) |
| mpBV->Release(); |
| |
| if( mpVW ) |
| mpVW->Release(); |
| |
| if( mpMP ) |
| mpMP->Release(); |
| |
| if( mpMS ) |
| mpMS->Release(); |
| |
| if( mpME ) |
| { |
| mpME->SetNotifyWindow( 0, WM_GRAPHNOTIFY, 0); |
| mpME->Release(); |
| } |
| |
| |
| if( mpMC ) |
| mpMC->Release(); |
| |
| if( mpEV ) |
| mpEV->Release(); |
| |
| if( mpOMF ) |
| mpOMF->Release(); |
| |
| if( mpGB ) |
| mpGB->Release(); |
| } |
| // ------------------------------------------------------------------------------ |
| bool Player::create( const ::rtl::OUString& rURL ) |
| { |
| HRESULT hR; |
| bool bRet = false; |
| |
| if( SUCCEEDED( hR = CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**) &mpGB ) ) ) |
| { |
| // Don't use the overlay mixer on Windows Vista |
| // It disables the desktop composition as soon as RenderFile is called |
| // also causes some other problems: video rendering is not reliable |
| if( !isWindowsVistaOrHigher() && SUCCEEDED( CoCreateInstance( CLSID_OverlayMixer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**) &mpOMF ) ) ) |
| { |
| mpGB->AddFilter( mpOMF, L"com_sun_star_media_OverlayMixerFilter" ); |
| |
| if( !SUCCEEDED( mpOMF->QueryInterface( IID_IDDrawExclModeVideo, (void**) &mpEV ) ) ) |
| mpEV = NULL; |
| } |
| |
| if( SUCCEEDED( hR = mpGB->RenderFile( reinterpret_cast<LPCWSTR>(rURL.getStr()), NULL ) ) && |
| SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaControl, (void**) &mpMC ) ) && |
| SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaEventEx, (void**) &mpME ) ) && |
| SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaSeeking, (void**) &mpMS ) ) && |
| SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaPosition, (void**) &mpMP ) ) ) |
| { |
| // Video interfaces |
| mpGB->QueryInterface( IID_IVideoWindow, (void**) &mpVW ); |
| mpGB->QueryInterface( IID_IBasicVideo, (void**) &mpBV ); |
| |
| // Audio interface |
| mpGB->QueryInterface( IID_IBasicAudio, (void**) &mpBA ); |
| |
| if( mpBA ) |
| mpBA->put_Volume( mnUnmutedVolume ); |
| |
| bRet = true; |
| } |
| } |
| |
| if( bRet ) |
| maURL = rURL; |
| else |
| maURL = ::rtl::OUString(); |
| |
| return bRet; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| const IVideoWindow* Player::getVideoWindow() const |
| { |
| return mpVW; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| void Player::setNotifyWnd( int nNotifyWnd ) |
| { |
| mbAddWindow = sal_False; |
| if( mpME ) |
| mpME->SetNotifyWindow( (OAHWND) nNotifyWnd, WM_GRAPHNOTIFY, reinterpret_cast< LONG_PTR>( this ) ); |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| void Player::setDDrawParams( IDirectDraw* pDDraw, IDirectDrawSurface* pDDrawSurface ) |
| { |
| if( mpEV && pDDraw && pDDrawSurface ) |
| { |
| mpEV->SetDDrawObject( pDDraw ); |
| mpEV->SetDDrawSurface( pDDrawSurface ); |
| } |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| long Player::processEvent() |
| { |
| long nCode, nParam1, nParam2; |
| |
| while( mpME && SUCCEEDED( mpME->GetEvent( &nCode, &nParam1, &nParam2, 0 ) ) ) |
| { |
| if( EC_COMPLETE == nCode ) |
| { |
| if( mbLooping ) |
| { |
| setMediaTime( 0.0 ); |
| start(); |
| } |
| else |
| { |
| setMediaTime( getDuration() ); |
| stop(); |
| } |
| } |
| |
| mpME->FreeEventParams( nCode, nParam1, nParam2 ); |
| } |
| |
| return 0; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| void SAL_CALL Player::start( ) |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| if( mpMC ) |
| { |
| if ( mbAddWindow ) |
| { |
| static WNDCLASS* mpWndClass = NULL; |
| if ( !mpWndClass ) |
| { |
| mpWndClass = new WNDCLASS; |
| |
| memset( mpWndClass, 0, sizeof( *mpWndClass ) ); |
| mpWndClass->hInstance = GetModuleHandle( NULL ); |
| mpWndClass->cbWndExtra = sizeof( DWORD ); |
| mpWndClass->lpfnWndProc = MediaPlayerWndProc_2; |
| mpWndClass->lpszClassName = "com_sun_star_media_Sound_Player"; |
| mpWndClass->hbrBackground = (HBRUSH) ::GetStockObject( BLACK_BRUSH ); |
| mpWndClass->hCursor = ::LoadCursor( NULL, IDC_ARROW ); |
| |
| ::RegisterClass( mpWndClass ); |
| } |
| if ( !mnFrameWnd ) |
| { |
| mnFrameWnd = (int) ::CreateWindow( mpWndClass->lpszClassName, NULL, |
| 0, |
| 0, 0, 0, 0, |
| (HWND) NULL, NULL, mpWndClass->hInstance, 0 ); |
| if ( mnFrameWnd ) |
| { |
| ::ShowWindow((HWND) mnFrameWnd, SW_HIDE); |
| ::SetWindowLong( (HWND) mnFrameWnd, 0, (DWORD) this ); |
| // mpVW->put_Owner( (OAHWND) mnFrameWnd ); |
| setNotifyWnd( mnFrameWnd ); |
| } |
| } |
| } |
| |
| mpMC->Run(); |
| } |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| void SAL_CALL Player::stop( ) |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| |
| if( mpMC ) |
| mpMC->Stop(); |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| sal_Bool SAL_CALL Player::isPlaying() |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| |
| OAFilterState eFilterState; |
| bool bRet = false; |
| |
| if( mpMC && SUCCEEDED( mpMC->GetState( 10, &eFilterState ) ) ) |
| bRet = ( State_Running == eFilterState ); |
| |
| return bRet; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| double SAL_CALL Player::getDuration( ) |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| |
| REFTIME aRefTime( 0.0 ); |
| |
| if( mpMP ) |
| mpMP->get_Duration( &aRefTime ); |
| |
| return aRefTime; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| void SAL_CALL Player::setMediaTime( double fTime ) |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| |
| if( mpMP ) |
| { |
| const bool bPlaying = isPlaying(); |
| |
| mpMP->put_CurrentPosition( fTime ); |
| |
| if( !bPlaying && mpMC ) |
| mpMC->StopWhenReady(); |
| } |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| double SAL_CALL Player::getMediaTime( ) |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| |
| REFTIME aRefTime( 0.0 ); |
| |
| if( mpMP ) |
| mpMP->get_CurrentPosition( &aRefTime ); |
| |
| return aRefTime; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| void SAL_CALL Player::setStopTime( double fTime ) |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| |
| if( mpMP ) |
| mpMP->put_StopTime( fTime ); |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| double SAL_CALL Player::getStopTime( ) |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| |
| REFTIME aRefTime( 0.0 ); |
| |
| if( mpMP ) |
| mpMP->get_StopTime( &aRefTime ); |
| |
| return aRefTime; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| void SAL_CALL Player::setRate( double fRate ) |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| |
| if( mpMP ) |
| mpMP->put_Rate( fRate ); |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| double SAL_CALL Player::getRate( ) |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| |
| double fRet( 0.0 ); |
| |
| if( mpMP ) |
| mpMP->get_Rate( &fRet ); |
| |
| return fRet; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet ) |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| |
| mbLooping = bSet; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| sal_Bool SAL_CALL Player::isPlaybackLoop( ) |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| |
| return mbLooping; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| void SAL_CALL Player::setMute( sal_Bool bSet ) |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| |
| if( mpBA && ( mbMuted != bSet ) ) |
| { |
| mbMuted = bSet; |
| mpBA->put_Volume( mbMuted ? -10000 : mnUnmutedVolume ); |
| } |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| sal_Bool SAL_CALL Player::isMute( ) |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| |
| return mbMuted; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB ) |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| |
| mnUnmutedVolume = static_cast< long >( nVolumeDB ) * 100; |
| |
| if( !mbMuted && mpBA ) |
| mpBA->put_Volume( mnUnmutedVolume ); |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| sal_Int16 SAL_CALL Player::getVolumeDB( ) |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| |
| return( static_cast< sal_Int16 >( mnUnmutedVolume / 100 ) ); |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| awt::Size SAL_CALL Player::getPreferredPlayerWindowSize( ) |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| |
| awt::Size aSize( 0, 0 ); |
| |
| if( mpBV ) |
| { |
| long nWidth = 0, nHeight = 0; |
| |
| mpBV->GetVideoSize( &nWidth, &nHeight ); |
| aSize.Width = nWidth; |
| aSize.Height = nHeight; |
| } |
| |
| return aSize; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( const uno::Sequence< uno::Any >& aArguments ) |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| |
| uno::Reference< ::media::XPlayerWindow > xRet; |
| awt::Size aSize( getPreferredPlayerWindowSize() ); |
| |
| if( mpVW && aSize.Width > 0 && aSize.Height > 0 ) |
| { |
| ::avmedia::win::Window* pWindow = new ::avmedia::win::Window( mxMgr, *this ); |
| |
| xRet = pWindow; |
| |
| if( !pWindow->create( aArguments ) ) |
| xRet = uno::Reference< ::media::XPlayerWindow >(); |
| } |
| |
| return xRet; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber( ) |
| throw (uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard(m_aMutex); |
| |
| uno::Reference< media::XFrameGrabber > xRet; |
| |
| if( !maURL.isEmpty() ) |
| { |
| FrameGrabber* pGrabber = new FrameGrabber( mxMgr ); |
| |
| xRet = pGrabber; |
| |
| if( !pGrabber->create( maURL ) ) |
| xRet.clear(); |
| } |
| |
| return xRet; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| ::rtl::OUString SAL_CALL Player::getImplementationName( ) |
| throw (uno::RuntimeException) |
| { |
| return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME ) ); |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| sal_Bool SAL_CALL Player::supportsService( const ::rtl::OUString& ServiceName ) |
| throw (uno::RuntimeException) |
| { |
| return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( AVMEDIA_WIN_PLAYER_SERVICENAME ) ); |
| } |
| |
| // ------------------------------------------------------------------------------ |
| |
| uno::Sequence< ::rtl::OUString > SAL_CALL Player::getSupportedServiceNames( ) |
| throw (uno::RuntimeException) |
| { |
| uno::Sequence< ::rtl::OUString > aRet(1); |
| aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( AVMEDIA_WIN_PLAYER_SERVICENAME ) ); |
| |
| return aRet; |
| } |
| |
| } // namespace win |
| } // namespace avmedia |