xref: /aoo42x/main/avmedia/source/win/player.cxx (revision 144e4e62)
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 
MediaPlayerWndProc_2(HWND hWnd,UINT nMsg,WPARAM nPar1,LPARAM nPar2)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 
isWindowsVistaOrHigher()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 
Player(const uno::Reference<lang::XMultiServiceFactory> & rxMgr)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 
~Player()113 Player::~Player()
114 {
115 	if( mnFrameWnd )
116         ::DestroyWindow( (HWND) mnFrameWnd );
117 
118     ::CoUninitialize();
119 }
120 
121 // ------------------------------------------------------------------------------
122 
disposing()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 // ------------------------------------------------------------------------------
create(const::rtl::OUString & rURL)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 
getVideoWindow() const210 const IVideoWindow* Player::getVideoWindow() const
211 {
212     return mpVW;
213 }
214 
215 // ------------------------------------------------------------------------------
216 
setNotifyWnd(int nNotifyWnd)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 
setDDrawParams(IDirectDraw * pDDraw,IDirectDrawSurface * pDDrawSurface)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 
processEvent()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 
start()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 
stop()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 
isPlaying()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 
getDuration()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 
setMediaTime(double fTime)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 
getMediaTime()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 
setStopTime(double fTime)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 
getStopTime()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 
setRate(double fRate)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 
getRate()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 
setPlaybackLoop(sal_Bool bSet)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 
isPlaybackLoop()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 
setMute(sal_Bool bSet)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 
isMute()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 
setVolumeDB(sal_Int16 nVolumeDB)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 
getVolumeDB()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 
getPreferredPlayerWindowSize()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 
createPlayerWindow(const uno::Sequence<uno::Any> & aArguments)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 
createFrameGrabber()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.isEmpty() )
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 
getImplementationName()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 
supportsService(const::rtl::OUString & ServiceName)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 
getSupportedServiceNames()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