nss: upgrade to release 3.73
[LibreOffice.git] / avmedia / source / win / player.cxx
blobb3e621cbc56d94840adf0ee195265af14e0b871b
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>
31 #include <osl/file.hxx>
33 #define AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Player_DirectX"
34 #define AVMEDIA_WIN_PLAYER_SERVICENAME "com.sun.star.media.Player_DirectX"
36 using namespace ::com::sun::star;
38 namespace avmedia::win {
40 static LRESULT CALLBACK MediaPlayerWndProc_2( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nPar2 )
42 Player* pPlayer = reinterpret_cast<Player*>(::GetWindowLongPtrW( hWnd, 0 ));
43 bool bProcessed = true;
45 if( pPlayer )
47 switch( nMsg )
49 case WM_GRAPHNOTIFY:
50 pPlayer->processEvent();
51 break;
52 default:
53 bProcessed = false;
54 break;
57 else
58 bProcessed = false;
60 return( bProcessed ? 0 : DefWindowProcW( hWnd, nMsg, nPar1, nPar2 ) );
64 Player::Player() :
65 Player_BASE(m_aMutex),
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 ::CoInitializeEx( nullptr, COINIT_APARTMENTTHREADED );
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 // tdf#128057: IGraphBuilder::RenderFile seems to fail to handle file URIs properly when
146 // they contain encoded characters like "%23"; so pass system path in that case instead.
147 OUString aFile(rURL);
148 if (aFile.startsWithIgnoreAsciiCase("file:"))
149 osl::FileBase::getSystemPathFromFileURL(rURL, aFile);
151 if( SUCCEEDED( hR = mpGB->RenderFile( o3tl::toW(aFile.getStr()), nullptr ) ) &&
152 SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaControl, reinterpret_cast<void**>(&mpMC) ) ) &&
153 SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaEventEx, reinterpret_cast<void**>(&mpME) ) ) &&
154 SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaSeeking, reinterpret_cast<void**>(&mpMS) ) ) &&
155 SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaPosition, reinterpret_cast<void**>(&mpMP) ) ) )
157 // Video interfaces
158 mpGB->QueryInterface( IID_IVideoWindow, reinterpret_cast<void**>(&mpVW) );
159 mpGB->QueryInterface( IID_IBasicVideo, reinterpret_cast<void**>(&mpBV) );
161 // Audio interface
162 mpGB->QueryInterface( IID_IBasicAudio, reinterpret_cast<void**>(&mpBA) );
164 if( mpBA )
165 mpBA->put_Volume( mnUnmutedVolume );
167 bRet = true;
171 if( bRet )
172 maURL = rURL;
173 else
174 maURL.clear();
176 return bRet;
180 const IVideoWindow* Player::getVideoWindow() const
182 return mpVW;
186 void Player::setNotifyWnd( HWND nNotifyWnd )
188 mbAddWindow = false;
189 if( mpME )
190 mpME->SetNotifyWindow( reinterpret_cast<OAHWND>(nNotifyWnd), WM_GRAPHNOTIFY, reinterpret_cast< LONG_PTR>( this ) );
194 long Player::processEvent()
196 long nCode;
197 LONG_PTR nParam1, nParam2;
199 while( mpME && SUCCEEDED( mpME->GetEvent( &nCode, &nParam1, &nParam2, 0 ) ) )
201 if( EC_COMPLETE == nCode )
203 if( mbLooping )
205 setMediaTime( 0.0 );
206 start();
208 else
210 setMediaTime( getDuration() );
211 stop();
215 mpME->FreeEventParams( nCode, nParam1, nParam2 );
218 return 0;
222 void SAL_CALL Player::start( )
224 ::osl::MutexGuard aGuard(m_aMutex);
225 if( mpMC )
227 if ( mbAddWindow )
229 static WNDCLASSW* mpWndClass = nullptr;
230 if ( !mpWndClass )
232 mpWndClass = new WNDCLASSW;
234 memset( mpWndClass, 0, sizeof( *mpWndClass ) );
235 mpWndClass->hInstance = GetModuleHandleW( nullptr );
236 mpWndClass->cbWndExtra = sizeof( DWORD );
237 mpWndClass->lpfnWndProc = MediaPlayerWndProc_2;
238 mpWndClass->lpszClassName = L"com_sun_star_media_Sound_Player";
239 mpWndClass->hbrBackground = static_cast<HBRUSH>(::GetStockObject( BLACK_BRUSH ));
240 mpWndClass->hCursor = ::LoadCursor( nullptr, IDC_ARROW );
242 RegisterClassW( mpWndClass );
244 if ( !mnFrameWnd )
246 mnFrameWnd = CreateWindowW( mpWndClass->lpszClassName, nullptr,
248 0, 0, 0, 0,
249 nullptr, nullptr, mpWndClass->hInstance, nullptr );
250 if ( mnFrameWnd )
252 ::ShowWindow(mnFrameWnd, SW_HIDE);
253 SetWindowLongPtrW( mnFrameWnd, 0, reinterpret_cast<LONG_PTR>(this) );
254 // mpVW->put_Owner( (OAHWND) mnFrameWnd );
255 setNotifyWnd( mnFrameWnd );
260 mpMC->Run();
265 void SAL_CALL Player::stop( )
267 ::osl::MutexGuard aGuard(m_aMutex);
268 if( mpMC )
269 mpMC->Stop();
273 sal_Bool SAL_CALL Player::isPlaying()
275 ::osl::MutexGuard aGuard(m_aMutex);
277 OAFilterState eFilterState;
278 bool bRet = false;
280 if( mpMC && SUCCEEDED( mpMC->GetState( 10, &eFilterState ) ) )
281 bRet = ( State_Running == eFilterState );
283 return bRet;
287 double SAL_CALL Player::getDuration( )
289 ::osl::MutexGuard aGuard(m_aMutex);
291 REFTIME aRefTime( 0.0 );
293 if( mpMP )
294 mpMP->get_Duration( &aRefTime );
296 return aRefTime;
300 void SAL_CALL Player::setMediaTime( double fTime )
302 ::osl::MutexGuard aGuard(m_aMutex);
304 if( mpMP )
306 const bool bPlaying = isPlaying();
308 mpMP->put_CurrentPosition( fTime );
310 if( !bPlaying && mpMC )
311 mpMC->StopWhenReady();
316 double SAL_CALL Player::getMediaTime( )
318 ::osl::MutexGuard aGuard(m_aMutex);
320 REFTIME aRefTime( 0.0 );
322 if( mpMP )
323 mpMP->get_CurrentPosition( &aRefTime );
325 return aRefTime;
329 void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet )
331 ::osl::MutexGuard aGuard(m_aMutex);
333 mbLooping = bSet;
337 sal_Bool SAL_CALL Player::isPlaybackLoop( )
339 ::osl::MutexGuard aGuard(m_aMutex);
341 return mbLooping;
345 void SAL_CALL Player::setMute( sal_Bool bSet )
347 ::osl::MutexGuard aGuard(m_aMutex);
349 if (mpBA && (mbMuted != static_cast<bool>(bSet)))
351 mbMuted = bSet;
352 mpBA->put_Volume( mbMuted ? -10000 : mnUnmutedVolume );
357 sal_Bool SAL_CALL Player::isMute( )
359 ::osl::MutexGuard aGuard(m_aMutex);
361 return mbMuted;
365 void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB )
367 ::osl::MutexGuard aGuard(m_aMutex);
369 mnUnmutedVolume = static_cast< long >( nVolumeDB ) * 100;
371 if( !mbMuted && mpBA )
372 mpBA->put_Volume( mnUnmutedVolume );
376 sal_Int16 SAL_CALL Player::getVolumeDB( )
378 ::osl::MutexGuard aGuard(m_aMutex);
380 return static_cast< sal_Int16 >( mnUnmutedVolume / 100 );
384 awt::Size SAL_CALL Player::getPreferredPlayerWindowSize( )
386 ::osl::MutexGuard aGuard(m_aMutex);
388 awt::Size aSize( 0, 0 );
390 if( mpBV )
392 long nWidth = 0, nHeight = 0;
394 mpBV->GetVideoSize( &nWidth, &nHeight );
395 aSize.Width = nWidth;
396 aSize.Height = nHeight;
399 return aSize;
403 uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( const uno::Sequence< uno::Any >& aArguments )
405 ::osl::MutexGuard aGuard(m_aMutex);
407 uno::Reference< ::media::XPlayerWindow > xRet;
408 awt::Size aSize( getPreferredPlayerWindowSize() );
410 if( mpVW && aSize.Width > 0 && aSize.Height > 0 )
412 ::avmedia::win::Window* pWindow = new ::avmedia::win::Window( *this );
414 xRet = pWindow;
416 if( !pWindow->create( aArguments ) )
417 xRet.clear();
420 return xRet;
424 uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber( )
426 uno::Reference< media::XFrameGrabber > xRet;
428 if( !maURL.isEmpty() )
430 FrameGrabber* pGrabber = new FrameGrabber();
432 xRet = pGrabber;
434 if( !pGrabber->create( maURL ) )
435 xRet.clear();
438 return xRet;
442 OUString SAL_CALL Player::getImplementationName( )
444 return AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME;
448 sal_Bool SAL_CALL Player::supportsService( const OUString& ServiceName )
450 return cppu::supportsService(this, ServiceName);
454 uno::Sequence< OUString > SAL_CALL Player::getSupportedServiceNames( )
456 return { AVMEDIA_WIN_PLAYER_SERVICENAME };
459 } // namespace avmedia::win
462 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */