bump product version to 6.3.0.0.beta1
[LibreOffice.git] / avmedia / source / win / player.cxx
blob7e3dd0a4965c92d52e02a2e7279edd23d01d4d1b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <objbase.h>
21 #include <strmif.h>
22 #include <control.h>
23 #include <uuids.h>
24 #include <evcode.h>
26 #include "player.hxx"
27 #include "framegrabber.hxx"
28 #include "window.hxx"
29 #include <cppuhelper/supportsservice.hxx>
30 #include <o3tl/char16_t2wchar_t.hxx>
32 #define AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Player_DirectX"
33 #define AVMEDIA_WIN_PLAYER_SERVICENAME "com.sun.star.media.Player_DirectX"
35 using namespace ::com::sun::star;
37 namespace avmedia { namespace win {
39 static LRESULT CALLBACK MediaPlayerWndProc_2( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nPar2 )
41 Player* pPlayer = reinterpret_cast<Player*>(::GetWindowLongPtrW( hWnd, 0 ));
42 bool bProcessed = true;
44 if( pPlayer )
46 switch( nMsg )
48 case WM_GRAPHNOTIFY:
49 pPlayer->processEvent();
50 break;
51 default:
52 bProcessed = false;
53 break;
56 else
57 bProcessed = false;
59 return( bProcessed ? 0 : DefWindowProcW( hWnd, nMsg, nPar1, nPar2 ) );
63 Player::Player( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) :
64 Player_BASE(m_aMutex),
65 mxMgr( rxMgr ),
66 mpGB( nullptr ),
67 mpOMF( nullptr ),
68 mpMC( nullptr ),
69 mpME( nullptr ),
70 mpMS( nullptr ),
71 mpMP( nullptr ),
72 mpBA( nullptr ),
73 mpBV( nullptr ),
74 mpVW( nullptr ),
75 mpEV( nullptr ),
76 mnUnmutedVolume( 0 ),
77 mnFrameWnd( nullptr ),
78 mbMuted( false ),
79 mbLooping( false ),
80 mbAddWindow( true )
82 ::CoInitialize( nullptr );
86 Player::~Player()
88 if( mnFrameWnd )
89 ::DestroyWindow( mnFrameWnd );
91 ::CoUninitialize();
95 void SAL_CALL Player::disposing()
97 ::osl::MutexGuard aGuard(m_aMutex);
98 stop();
99 if( mpBA )
100 mpBA->Release();
102 if( mpBV )
103 mpBV->Release();
105 if( mpVW )
106 mpVW->Release();
108 if( mpMP )
109 mpMP->Release();
111 if( mpMS )
112 mpMS->Release();
114 if( mpME )
116 mpME->SetNotifyWindow( 0, WM_GRAPHNOTIFY, 0);
117 mpME->Release();
120 if( mpMC )
121 mpMC->Release();
123 if( mpEV )
124 mpEV->Release();
126 if( mpOMF )
127 mpOMF->Release();
129 if( mpGB )
130 mpGB->Release();
134 bool Player::create( const OUString& rURL )
136 HRESULT hR;
137 bool bRet = false;
139 if( SUCCEEDED( hR = CoCreateInstance( CLSID_FilterGraph, nullptr, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, reinterpret_cast<void**>(&mpGB) ) ) )
141 // Don't use the overlay mixer on Windows Vista
142 // It disables the desktop composition as soon as RenderFile is called
143 // also causes some other problems: video rendering is not reliable
145 if( SUCCEEDED( hR = mpGB->RenderFile( o3tl::toW(rURL.getStr()), nullptr ) ) &&
146 SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaControl, reinterpret_cast<void**>(&mpMC) ) ) &&
147 SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaEventEx, reinterpret_cast<void**>(&mpME) ) ) &&
148 SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaSeeking, reinterpret_cast<void**>(&mpMS) ) ) &&
149 SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaPosition, reinterpret_cast<void**>(&mpMP) ) ) )
151 // Video interfaces
152 mpGB->QueryInterface( IID_IVideoWindow, reinterpret_cast<void**>(&mpVW) );
153 mpGB->QueryInterface( IID_IBasicVideo, reinterpret_cast<void**>(&mpBV) );
155 // Audio interface
156 mpGB->QueryInterface( IID_IBasicAudio, reinterpret_cast<void**>(&mpBA) );
158 if( mpBA )
159 mpBA->put_Volume( mnUnmutedVolume );
161 bRet = true;
165 if( bRet )
166 maURL = rURL;
167 else
168 maURL.clear();
170 return bRet;
174 const IVideoWindow* Player::getVideoWindow() const
176 return mpVW;
180 void Player::setNotifyWnd( HWND nNotifyWnd )
182 mbAddWindow = false;
183 if( mpME )
184 mpME->SetNotifyWindow( reinterpret_cast<OAHWND>(nNotifyWnd), WM_GRAPHNOTIFY, reinterpret_cast< LONG_PTR>( this ) );
188 long Player::processEvent()
190 long nCode;
191 LONG_PTR nParam1, nParam2;
193 while( mpME && SUCCEEDED( mpME->GetEvent( &nCode, &nParam1, &nParam2, 0 ) ) )
195 if( EC_COMPLETE == nCode )
197 if( mbLooping )
199 setMediaTime( 0.0 );
200 start();
202 else
204 setMediaTime( getDuration() );
205 stop();
209 mpME->FreeEventParams( nCode, nParam1, nParam2 );
212 return 0;
216 void SAL_CALL Player::start( )
218 ::osl::MutexGuard aGuard(m_aMutex);
219 if( mpMC )
221 if ( mbAddWindow )
223 static WNDCLASSW* mpWndClass = nullptr;
224 if ( !mpWndClass )
226 mpWndClass = new WNDCLASSW;
228 memset( mpWndClass, 0, sizeof( *mpWndClass ) );
229 mpWndClass->hInstance = GetModuleHandleW( nullptr );
230 mpWndClass->cbWndExtra = sizeof( DWORD );
231 mpWndClass->lpfnWndProc = MediaPlayerWndProc_2;
232 mpWndClass->lpszClassName = L"com_sun_star_media_Sound_Player";
233 mpWndClass->hbrBackground = static_cast<HBRUSH>(::GetStockObject( BLACK_BRUSH ));
234 mpWndClass->hCursor = ::LoadCursor( nullptr, IDC_ARROW );
236 RegisterClassW( mpWndClass );
238 if ( !mnFrameWnd )
240 mnFrameWnd = CreateWindowW( mpWndClass->lpszClassName, nullptr,
242 0, 0, 0, 0,
243 nullptr, nullptr, mpWndClass->hInstance, nullptr );
244 if ( mnFrameWnd )
246 ::ShowWindow(mnFrameWnd, SW_HIDE);
247 SetWindowLongPtrW( mnFrameWnd, 0, reinterpret_cast<LONG_PTR>(this) );
248 // mpVW->put_Owner( (OAHWND) mnFrameWnd );
249 setNotifyWnd( mnFrameWnd );
254 mpMC->Run();
259 void SAL_CALL Player::stop( )
261 ::osl::MutexGuard aGuard(m_aMutex);
262 if( mpMC )
263 mpMC->Stop();
267 sal_Bool SAL_CALL Player::isPlaying()
269 ::osl::MutexGuard aGuard(m_aMutex);
271 OAFilterState eFilterState;
272 bool bRet = false;
274 if( mpMC && SUCCEEDED( mpMC->GetState( 10, &eFilterState ) ) )
275 bRet = ( State_Running == eFilterState );
277 return bRet;
281 double SAL_CALL Player::getDuration( )
283 ::osl::MutexGuard aGuard(m_aMutex);
285 REFTIME aRefTime( 0.0 );
287 if( mpMP )
288 mpMP->get_Duration( &aRefTime );
290 return aRefTime;
294 void SAL_CALL Player::setMediaTime( double fTime )
296 ::osl::MutexGuard aGuard(m_aMutex);
298 if( mpMP )
300 const bool bPlaying = isPlaying();
302 mpMP->put_CurrentPosition( fTime );
304 if( !bPlaying && mpMC )
305 mpMC->StopWhenReady();
310 double SAL_CALL Player::getMediaTime( )
312 ::osl::MutexGuard aGuard(m_aMutex);
314 REFTIME aRefTime( 0.0 );
316 if( mpMP )
317 mpMP->get_CurrentPosition( &aRefTime );
319 return aRefTime;
323 void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet )
325 ::osl::MutexGuard aGuard(m_aMutex);
327 mbLooping = bSet;
331 sal_Bool SAL_CALL Player::isPlaybackLoop( )
333 ::osl::MutexGuard aGuard(m_aMutex);
335 return mbLooping;
339 void SAL_CALL Player::setMute( sal_Bool bSet )
341 ::osl::MutexGuard aGuard(m_aMutex);
343 if (mpBA && (mbMuted != static_cast<bool>(bSet)))
345 mbMuted = bSet;
346 mpBA->put_Volume( mbMuted ? -10000 : mnUnmutedVolume );
351 sal_Bool SAL_CALL Player::isMute( )
353 ::osl::MutexGuard aGuard(m_aMutex);
355 return mbMuted;
359 void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB )
361 ::osl::MutexGuard aGuard(m_aMutex);
363 mnUnmutedVolume = static_cast< long >( nVolumeDB ) * 100;
365 if( !mbMuted && mpBA )
366 mpBA->put_Volume( mnUnmutedVolume );
370 sal_Int16 SAL_CALL Player::getVolumeDB( )
372 ::osl::MutexGuard aGuard(m_aMutex);
374 return static_cast< sal_Int16 >( mnUnmutedVolume / 100 );
378 awt::Size SAL_CALL Player::getPreferredPlayerWindowSize( )
380 ::osl::MutexGuard aGuard(m_aMutex);
382 awt::Size aSize( 0, 0 );
384 if( mpBV )
386 long nWidth = 0, nHeight = 0;
388 mpBV->GetVideoSize( &nWidth, &nHeight );
389 aSize.Width = nWidth;
390 aSize.Height = nHeight;
393 return aSize;
397 uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( const uno::Sequence< uno::Any >& aArguments )
399 ::osl::MutexGuard aGuard(m_aMutex);
401 uno::Reference< ::media::XPlayerWindow > xRet;
402 awt::Size aSize( getPreferredPlayerWindowSize() );
404 if( mpVW && aSize.Width > 0 && aSize.Height > 0 )
406 ::avmedia::win::Window* pWindow = new ::avmedia::win::Window( mxMgr, *this );
408 xRet = pWindow;
410 if( !pWindow->create( aArguments ) )
411 xRet.clear();
414 return xRet;
418 uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber( )
420 uno::Reference< media::XFrameGrabber > xRet;
422 if( !maURL.isEmpty() )
424 FrameGrabber* pGrabber = new FrameGrabber( mxMgr );
426 xRet = pGrabber;
428 if( !pGrabber->create( maURL ) )
429 xRet.clear();
432 return xRet;
436 OUString SAL_CALL Player::getImplementationName( )
438 return OUString( AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME );
442 sal_Bool SAL_CALL Player::supportsService( const OUString& ServiceName )
444 return cppu::supportsService(this, ServiceName);
448 uno::Sequence< OUString > SAL_CALL Player::getSupportedServiceNames( )
450 return { AVMEDIA_WIN_PLAYER_SERVICENAME };
453 } // namespace win
454 } // namespace avmedia
456 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */