1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
27 #include "framegrabber.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;
50 pPlayer
->processEvent();
60 return( bProcessed
? 0 : DefWindowProcW( hWnd
, nMsg
, nPar1
, nPar2
) );
65 Player_BASE(m_aMutex
),
77 mnFrameWnd( nullptr ),
82 ::CoInitializeEx( nullptr, COINIT_APARTMENTTHREADED
);
89 ::DestroyWindow( mnFrameWnd
);
95 void SAL_CALL
Player::disposing()
97 ::osl::MutexGuard
aGuard(m_aMutex
);
116 mpME
->SetNotifyWindow( 0, WM_GRAPHNOTIFY
, 0);
134 bool Player::create( const OUString
& rURL
)
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
) ) ) )
158 mpGB
->QueryInterface( IID_IVideoWindow
, reinterpret_cast<void**>(&mpVW
) );
159 mpGB
->QueryInterface( IID_IBasicVideo
, reinterpret_cast<void**>(&mpBV
) );
162 mpGB
->QueryInterface( IID_IBasicAudio
, reinterpret_cast<void**>(&mpBA
) );
165 mpBA
->put_Volume( mnUnmutedVolume
);
180 const IVideoWindow
* Player::getVideoWindow() const
186 void Player::setNotifyWnd( HWND nNotifyWnd
)
190 mpME
->SetNotifyWindow( reinterpret_cast<OAHWND
>(nNotifyWnd
), WM_GRAPHNOTIFY
, reinterpret_cast< LONG_PTR
>( this ) );
194 long Player::processEvent()
197 LONG_PTR nParam1
, nParam2
;
199 while( mpME
&& SUCCEEDED( mpME
->GetEvent( &nCode
, &nParam1
, &nParam2
, 0 ) ) )
201 if( EC_COMPLETE
== nCode
)
210 setMediaTime( getDuration() );
215 mpME
->FreeEventParams( nCode
, nParam1
, nParam2
);
222 void SAL_CALL
Player::start( )
224 ::osl::MutexGuard
aGuard(m_aMutex
);
229 static WNDCLASSW
* mpWndClass
= nullptr;
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
);
246 mnFrameWnd
= CreateWindowW( mpWndClass
->lpszClassName
, nullptr,
249 nullptr, nullptr, mpWndClass
->hInstance
, nullptr );
252 ::ShowWindow(mnFrameWnd
, SW_HIDE
);
253 SetWindowLongPtrW( mnFrameWnd
, 0, reinterpret_cast<LONG_PTR
>(this) );
254 // mpVW->put_Owner( (OAHWND) mnFrameWnd );
255 setNotifyWnd( mnFrameWnd
);
265 void SAL_CALL
Player::stop( )
267 ::osl::MutexGuard
aGuard(m_aMutex
);
273 sal_Bool SAL_CALL
Player::isPlaying()
275 ::osl::MutexGuard
aGuard(m_aMutex
);
277 OAFilterState eFilterState
;
280 if( mpMC
&& SUCCEEDED( mpMC
->GetState( 10, &eFilterState
) ) )
281 bRet
= ( State_Running
== eFilterState
);
287 double SAL_CALL
Player::getDuration( )
289 ::osl::MutexGuard
aGuard(m_aMutex
);
291 REFTIME
aRefTime( 0.0 );
294 mpMP
->get_Duration( &aRefTime
);
300 void SAL_CALL
Player::setMediaTime( double fTime
)
302 ::osl::MutexGuard
aGuard(m_aMutex
);
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 );
323 mpMP
->get_CurrentPosition( &aRefTime
);
329 void SAL_CALL
Player::setPlaybackLoop( sal_Bool bSet
)
331 ::osl::MutexGuard
aGuard(m_aMutex
);
337 sal_Bool SAL_CALL
Player::isPlaybackLoop( )
339 ::osl::MutexGuard
aGuard(m_aMutex
);
345 void SAL_CALL
Player::setMute( sal_Bool bSet
)
347 ::osl::MutexGuard
aGuard(m_aMutex
);
349 if (mpBA
&& (mbMuted
!= static_cast<bool>(bSet
)))
352 mpBA
->put_Volume( mbMuted
? -10000 : mnUnmutedVolume
);
357 sal_Bool SAL_CALL
Player::isMute( )
359 ::osl::MutexGuard
aGuard(m_aMutex
);
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 );
392 long nWidth
= 0, nHeight
= 0;
394 mpBV
->GetVideoSize( &nWidth
, &nHeight
);
395 aSize
.Width
= nWidth
;
396 aSize
.Height
= nHeight
;
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 );
416 if( !pWindow
->create( aArguments
) )
424 uno::Reference
< media::XFrameGrabber
> SAL_CALL
Player::createFrameGrabber( )
426 uno::Reference
< media::XFrameGrabber
> xRet
;
428 if( !maURL
.isEmpty() )
430 FrameGrabber
* pGrabber
= new FrameGrabber();
434 if( !pGrabber
->create( maURL
) )
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: */