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 {
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 {
312 ::osl::MutexGuard aGuard(m_aMutex);
313
314 if( mpMC )
315 mpMC->Stop();
316 }
317
318 // ------------------------------------------------------------------------------
319
isPlaying()320 sal_Bool SAL_CALL Player::isPlaying()
321 {
322 ::osl::MutexGuard aGuard(m_aMutex);
323
324 OAFilterState eFilterState;
325 bool bRet = false;
326
327 if( mpMC && SUCCEEDED( mpMC->GetState( 10, &eFilterState ) ) )
328 bRet = ( State_Running == eFilterState );
329
330 return bRet;
331 }
332
333 // ------------------------------------------------------------------------------
334
getDuration()335 double SAL_CALL Player::getDuration( )
336 {
337 ::osl::MutexGuard aGuard(m_aMutex);
338
339 REFTIME aRefTime( 0.0 );
340
341 if( mpMP )
342 mpMP->get_Duration( &aRefTime );
343
344 return aRefTime;
345 }
346
347 // ------------------------------------------------------------------------------
348
setMediaTime(double fTime)349 void SAL_CALL Player::setMediaTime( double fTime )
350 {
351 ::osl::MutexGuard aGuard(m_aMutex);
352
353 if( mpMP )
354 {
355 const bool bPlaying = isPlaying();
356
357 mpMP->put_CurrentPosition( fTime );
358
359 if( !bPlaying && mpMC )
360 mpMC->StopWhenReady();
361 }
362 }
363
364 // ------------------------------------------------------------------------------
365
getMediaTime()366 double SAL_CALL Player::getMediaTime( )
367 {
368 ::osl::MutexGuard aGuard(m_aMutex);
369
370 REFTIME aRefTime( 0.0 );
371
372 if( mpMP )
373 mpMP->get_CurrentPosition( &aRefTime );
374
375 return aRefTime;
376 }
377
378 // ------------------------------------------------------------------------------
379
setStopTime(double fTime)380 void SAL_CALL Player::setStopTime( double fTime )
381 {
382 ::osl::MutexGuard aGuard(m_aMutex);
383
384 if( mpMP )
385 mpMP->put_StopTime( fTime );
386 }
387
388 // ------------------------------------------------------------------------------
389
getStopTime()390 double SAL_CALL Player::getStopTime( )
391 {
392 ::osl::MutexGuard aGuard(m_aMutex);
393
394 REFTIME aRefTime( 0.0 );
395
396 if( mpMP )
397 mpMP->get_StopTime( &aRefTime );
398
399 return aRefTime;
400 }
401
402 // ------------------------------------------------------------------------------
403
setRate(double fRate)404 void SAL_CALL Player::setRate( double fRate )
405 {
406 ::osl::MutexGuard aGuard(m_aMutex);
407
408 if( mpMP )
409 mpMP->put_Rate( fRate );
410 }
411
412 // ------------------------------------------------------------------------------
413
getRate()414 double SAL_CALL Player::getRate( )
415 {
416 ::osl::MutexGuard aGuard(m_aMutex);
417
418 double fRet( 0.0 );
419
420 if( mpMP )
421 mpMP->get_Rate( &fRet );
422
423 return fRet;
424 }
425
426 // ------------------------------------------------------------------------------
427
setPlaybackLoop(sal_Bool bSet)428 void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet )
429 {
430 ::osl::MutexGuard aGuard(m_aMutex);
431
432 mbLooping = bSet;
433 }
434
435 // ------------------------------------------------------------------------------
436
isPlaybackLoop()437 sal_Bool SAL_CALL Player::isPlaybackLoop( )
438 {
439 ::osl::MutexGuard aGuard(m_aMutex);
440
441 return mbLooping;
442 }
443
444 // ------------------------------------------------------------------------------
445
setMute(sal_Bool bSet)446 void SAL_CALL Player::setMute( sal_Bool bSet )
447 {
448 ::osl::MutexGuard aGuard(m_aMutex);
449
450 if( mpBA && ( mbMuted != bSet ) )
451 {
452 mbMuted = bSet;
453 mpBA->put_Volume( mbMuted ? -10000 : mnUnmutedVolume );
454 }
455 }
456
457 // ------------------------------------------------------------------------------
458
isMute()459 sal_Bool SAL_CALL Player::isMute( )
460 {
461 ::osl::MutexGuard aGuard(m_aMutex);
462
463 return mbMuted;
464 }
465
466 // ------------------------------------------------------------------------------
467
setVolumeDB(sal_Int16 nVolumeDB)468 void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB )
469 {
470 ::osl::MutexGuard aGuard(m_aMutex);
471
472 mnUnmutedVolume = static_cast< long >( nVolumeDB ) * 100;
473
474 if( !mbMuted && mpBA )
475 mpBA->put_Volume( mnUnmutedVolume );
476 }
477
478 // ------------------------------------------------------------------------------
479
getVolumeDB()480 sal_Int16 SAL_CALL Player::getVolumeDB( )
481 {
482 ::osl::MutexGuard aGuard(m_aMutex);
483
484 return( static_cast< sal_Int16 >( mnUnmutedVolume / 100 ) );
485 }
486
487 // ------------------------------------------------------------------------------
488
getPreferredPlayerWindowSize()489 awt::Size SAL_CALL Player::getPreferredPlayerWindowSize( )
490 {
491 ::osl::MutexGuard aGuard(m_aMutex);
492
493 awt::Size aSize( 0, 0 );
494
495 if( mpBV )
496 {
497 long nWidth = 0, nHeight = 0;
498
499 mpBV->GetVideoSize( &nWidth, &nHeight );
500 aSize.Width = nWidth;
501 aSize.Height = nHeight;
502 }
503
504 return aSize;
505 }
506
507 // ------------------------------------------------------------------------------
508
createPlayerWindow(const uno::Sequence<uno::Any> & aArguments)509 uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( const uno::Sequence< uno::Any >& aArguments )
510 {
511 ::osl::MutexGuard aGuard(m_aMutex);
512
513 uno::Reference< ::media::XPlayerWindow > xRet;
514 awt::Size aSize( getPreferredPlayerWindowSize() );
515
516 if( mpVW && aSize.Width > 0 && aSize.Height > 0 )
517 {
518 ::avmedia::win::Window* pWindow = new ::avmedia::win::Window( mxContext, *this );
519
520 xRet = pWindow;
521
522 if( !pWindow->create( aArguments ) )
523 xRet = uno::Reference< ::media::XPlayerWindow >();
524 }
525
526 return xRet;
527 }
528
529 // ------------------------------------------------------------------------------
530
createFrameGrabber()531 uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber( )
532 {
533 ::osl::MutexGuard aGuard(m_aMutex);
534
535 uno::Reference< media::XFrameGrabber > xRet;
536
537 if( !maURL.isEmpty() )
538 {
539 FrameGrabber* pGrabber = new FrameGrabber( mxContext );
540
541 xRet = pGrabber;
542
543 if( !pGrabber->create( maURL ) )
544 xRet.clear();
545 }
546
547 return xRet;
548 }
549
550 // ------------------------------------------------------------------------------
551
getImplementationName()552 ::rtl::OUString SAL_CALL Player::getImplementationName( )
553 {
554 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME ) );
555 }
556
557 // ------------------------------------------------------------------------------
558
supportsService(const::rtl::OUString & ServiceName)559 sal_Bool SAL_CALL Player::supportsService( const ::rtl::OUString& ServiceName )
560 {
561 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( AVMEDIA_WIN_PLAYER_SERVICENAME ) );
562 }
563
564 // ------------------------------------------------------------------------------
565
getSupportedServiceNames()566 uno::Sequence< ::rtl::OUString > SAL_CALL Player::getSupportedServiceNames( )
567 {
568 uno::Sequence< ::rtl::OUString > aRet(1);
569 aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( AVMEDIA_WIN_PLAYER_SERVICENAME ) );
570
571 return aRet;
572 }
573
574 } // namespace win
575 } // namespace avmedia
576