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