xref: /trunk/main/avmedia/source/win/player.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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