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