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<uno::XComponentContext> & rxContext)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
~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;
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
start()266 void SAL_CALL Player::start( )
267 throw (uno::RuntimeException)
268 {
269 ::osl::MutexGuard aGuard(m_aMutex);
270 if( mpMC )
271 {
272 if ( mbAddWindow )
273 {
274 static WNDCLASS* mpWndClass = NULL;
275 if ( !mpWndClass )
276 {
277 mpWndClass = new WNDCLASS;
278
279 memset( mpWndClass, 0, sizeof( *mpWndClass ) );
280 mpWndClass->hInstance = GetModuleHandle( NULL );
281 mpWndClass->cbWndExtra = sizeof( DWORD );
282 mpWndClass->lpfnWndProc = MediaPlayerWndProc_2;
283 mpWndClass->lpszClassName = "com_sun_star_media_Sound_Player";
284 mpWndClass->hbrBackground = (HBRUSH) ::GetStockObject( BLACK_BRUSH );
285 mpWndClass->hCursor = ::LoadCursor( NULL, IDC_ARROW );
286
287 ::RegisterClass( mpWndClass );
288 }
289 if ( !mnFrameWnd )
290 {
291 mnFrameWnd = (int) ::CreateWindow( mpWndClass->lpszClassName, NULL,
292 0,
293 0, 0, 0, 0,
294 (HWND) NULL, NULL, mpWndClass->hInstance, 0 );
295 if ( mnFrameWnd )
296 {
297 ::ShowWindow((HWND) mnFrameWnd, SW_HIDE);
298 ::SetWindowLong( (HWND) mnFrameWnd, 0, (DWORD) this );
299 // mpVW->put_Owner( (OAHWND) mnFrameWnd );
300 setNotifyWnd( mnFrameWnd );
301 }
302 }
303 }
304
305 mpMC->Run();
306 }
307 }
308
309 // ------------------------------------------------------------------------------
310
stop()311 void SAL_CALL Player::stop( )
312 throw (uno::RuntimeException)
313 {
314 ::osl::MutexGuard aGuard(m_aMutex);
315
316 if( mpMC )
317 mpMC->Stop();
318 }
319
320 // ------------------------------------------------------------------------------
321
isPlaying()322 sal_Bool SAL_CALL Player::isPlaying()
323 throw (uno::RuntimeException)
324 {
325 ::osl::MutexGuard aGuard(m_aMutex);
326
327 OAFilterState eFilterState;
328 bool bRet = false;
329
330 if( mpMC && SUCCEEDED( mpMC->GetState( 10, &eFilterState ) ) )
331 bRet = ( State_Running == eFilterState );
332
333 return bRet;
334 }
335
336 // ------------------------------------------------------------------------------
337
getDuration()338 double SAL_CALL Player::getDuration( )
339 throw (uno::RuntimeException)
340 {
341 ::osl::MutexGuard aGuard(m_aMutex);
342
343 REFTIME aRefTime( 0.0 );
344
345 if( mpMP )
346 mpMP->get_Duration( &aRefTime );
347
348 return aRefTime;
349 }
350
351 // ------------------------------------------------------------------------------
352
setMediaTime(double fTime)353 void SAL_CALL Player::setMediaTime( double fTime )
354 throw (uno::RuntimeException)
355 {
356 ::osl::MutexGuard aGuard(m_aMutex);
357
358 if( mpMP )
359 {
360 const bool bPlaying = isPlaying();
361
362 mpMP->put_CurrentPosition( fTime );
363
364 if( !bPlaying && mpMC )
365 mpMC->StopWhenReady();
366 }
367 }
368
369 // ------------------------------------------------------------------------------
370
getMediaTime()371 double SAL_CALL Player::getMediaTime( )
372 throw (uno::RuntimeException)
373 {
374 ::osl::MutexGuard aGuard(m_aMutex);
375
376 REFTIME aRefTime( 0.0 );
377
378 if( mpMP )
379 mpMP->get_CurrentPosition( &aRefTime );
380
381 return aRefTime;
382 }
383
384 // ------------------------------------------------------------------------------
385
setStopTime(double fTime)386 void SAL_CALL Player::setStopTime( double fTime )
387 throw (uno::RuntimeException)
388 {
389 ::osl::MutexGuard aGuard(m_aMutex);
390
391 if( mpMP )
392 mpMP->put_StopTime( fTime );
393 }
394
395 // ------------------------------------------------------------------------------
396
getStopTime()397 double SAL_CALL Player::getStopTime( )
398 throw (uno::RuntimeException)
399 {
400 ::osl::MutexGuard aGuard(m_aMutex);
401
402 REFTIME aRefTime( 0.0 );
403
404 if( mpMP )
405 mpMP->get_StopTime( &aRefTime );
406
407 return aRefTime;
408 }
409
410 // ------------------------------------------------------------------------------
411
setRate(double fRate)412 void SAL_CALL Player::setRate( double fRate )
413 throw (uno::RuntimeException)
414 {
415 ::osl::MutexGuard aGuard(m_aMutex);
416
417 if( mpMP )
418 mpMP->put_Rate( fRate );
419 }
420
421 // ------------------------------------------------------------------------------
422
getRate()423 double SAL_CALL Player::getRate( )
424 throw (uno::RuntimeException)
425 {
426 ::osl::MutexGuard aGuard(m_aMutex);
427
428 double fRet( 0.0 );
429
430 if( mpMP )
431 mpMP->get_Rate( &fRet );
432
433 return fRet;
434 }
435
436 // ------------------------------------------------------------------------------
437
setPlaybackLoop(sal_Bool bSet)438 void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet )
439 throw (uno::RuntimeException)
440 {
441 ::osl::MutexGuard aGuard(m_aMutex);
442
443 mbLooping = bSet;
444 }
445
446 // ------------------------------------------------------------------------------
447
isPlaybackLoop()448 sal_Bool SAL_CALL Player::isPlaybackLoop( )
449 throw (uno::RuntimeException)
450 {
451 ::osl::MutexGuard aGuard(m_aMutex);
452
453 return mbLooping;
454 }
455
456 // ------------------------------------------------------------------------------
457
setMute(sal_Bool bSet)458 void SAL_CALL Player::setMute( sal_Bool bSet )
459 throw (uno::RuntimeException)
460 {
461 ::osl::MutexGuard aGuard(m_aMutex);
462
463 if( mpBA && ( mbMuted != bSet ) )
464 {
465 mbMuted = bSet;
466 mpBA->put_Volume( mbMuted ? -10000 : mnUnmutedVolume );
467 }
468 }
469
470 // ------------------------------------------------------------------------------
471
isMute()472 sal_Bool SAL_CALL Player::isMute( )
473 throw (uno::RuntimeException)
474 {
475 ::osl::MutexGuard aGuard(m_aMutex);
476
477 return mbMuted;
478 }
479
480 // ------------------------------------------------------------------------------
481
setVolumeDB(sal_Int16 nVolumeDB)482 void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB )
483 throw (uno::RuntimeException)
484 {
485 ::osl::MutexGuard aGuard(m_aMutex);
486
487 mnUnmutedVolume = static_cast< long >( nVolumeDB ) * 100;
488
489 if( !mbMuted && mpBA )
490 mpBA->put_Volume( mnUnmutedVolume );
491 }
492
493 // ------------------------------------------------------------------------------
494
getVolumeDB()495 sal_Int16 SAL_CALL Player::getVolumeDB( )
496 throw (uno::RuntimeException)
497 {
498 ::osl::MutexGuard aGuard(m_aMutex);
499
500 return( static_cast< sal_Int16 >( mnUnmutedVolume / 100 ) );
501 }
502
503 // ------------------------------------------------------------------------------
504
getPreferredPlayerWindowSize()505 awt::Size SAL_CALL Player::getPreferredPlayerWindowSize( )
506 throw (uno::RuntimeException)
507 {
508 ::osl::MutexGuard aGuard(m_aMutex);
509
510 awt::Size aSize( 0, 0 );
511
512 if( mpBV )
513 {
514 long nWidth = 0, nHeight = 0;
515
516 mpBV->GetVideoSize( &nWidth, &nHeight );
517 aSize.Width = nWidth;
518 aSize.Height = nHeight;
519 }
520
521 return aSize;
522 }
523
524 // ------------------------------------------------------------------------------
525
createPlayerWindow(const uno::Sequence<uno::Any> & aArguments)526 uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( const uno::Sequence< uno::Any >& aArguments )
527 throw (uno::RuntimeException)
528 {
529 ::osl::MutexGuard aGuard(m_aMutex);
530
531 uno::Reference< ::media::XPlayerWindow > xRet;
532 awt::Size aSize( getPreferredPlayerWindowSize() );
533
534 if( mpVW && aSize.Width > 0 && aSize.Height > 0 )
535 {
536 ::avmedia::win::Window* pWindow = new ::avmedia::win::Window( mxContext, *this );
537
538 xRet = pWindow;
539
540 if( !pWindow->create( aArguments ) )
541 xRet = uno::Reference< ::media::XPlayerWindow >();
542 }
543
544 return xRet;
545 }
546
547 // ------------------------------------------------------------------------------
548
createFrameGrabber()549 uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber( )
550 throw (uno::RuntimeException)
551 {
552 ::osl::MutexGuard aGuard(m_aMutex);
553
554 uno::Reference< media::XFrameGrabber > xRet;
555
556 if( !maURL.isEmpty() )
557 {
558 FrameGrabber* pGrabber = new FrameGrabber( mxContext );
559
560 xRet = pGrabber;
561
562 if( !pGrabber->create( maURL ) )
563 xRet.clear();
564 }
565
566 return xRet;
567 }
568
569 // ------------------------------------------------------------------------------
570
getImplementationName()571 ::rtl::OUString SAL_CALL Player::getImplementationName( )
572 throw (uno::RuntimeException)
573 {
574 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME ) );
575 }
576
577 // ------------------------------------------------------------------------------
578
supportsService(const::rtl::OUString & ServiceName)579 sal_Bool SAL_CALL Player::supportsService( const ::rtl::OUString& ServiceName )
580 throw (uno::RuntimeException)
581 {
582 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( AVMEDIA_WIN_PLAYER_SERVICENAME ) );
583 }
584
585 // ------------------------------------------------------------------------------
586
getSupportedServiceNames()587 uno::Sequence< ::rtl::OUString > SAL_CALL Player::getSupportedServiceNames( )
588 throw (uno::RuntimeException)
589 {
590 uno::Sequence< ::rtl::OUString > aRet(1);
591 aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( AVMEDIA_WIN_PLAYER_SERVICENAME ) );
592
593 return aRet;
594 }
595
596 } // namespace win
597 } // namespace avmedia
598