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