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>
32 #include <rtl/ref.hxx>
34 constexpr OUStringLiteral AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME
= u
"com.sun.star.comp.avmedia.Player_DirectX";
35 constexpr OUString AVMEDIA_WIN_PLAYER_SERVICENAME
= u
"com.sun.star.media.Player_DirectX"_ustr
;
37 using namespace ::com::sun::star
;
39 namespace avmedia::win
{
41 static LRESULT CALLBACK
MediaPlayerWndProc_2( HWND hWnd
,UINT nMsg
, WPARAM nPar1
, LPARAM nPar2
)
43 Player
* pPlayer
= reinterpret_cast<Player
*>(::GetWindowLongPtrW( hWnd
, 0 ));
44 bool bProcessed
= true;
51 pPlayer
->processEvent();
61 return( bProcessed
? 0 : DefWindowProcW( hWnd
, nMsg
, nPar1
, nPar2
) );
66 Player_BASE(m_aMutex
),
67 sal::systools::CoInitializeGuard(COINIT_APARTMENTTHREADED
, false,
68 sal::systools::CoInitializeGuard::WhenFailed::NoThrow
),
70 mnFrameWnd( nullptr ),
81 ::DestroyWindow( mnFrameWnd
);
85 void SAL_CALL
Player::disposing()
87 ::osl::MutexGuard
aGuard(m_aMutex
);
90 mpME
->SetNotifyWindow( 0, WM_GRAPHNOTIFY
, 0);
94 bool Player::create( const OUString
& rURL
)
98 if( SUCCEEDED(mpGB
.CoCreateInstance(CLSID_FilterGraph
, nullptr, CLSCTX_INPROC_SERVER
)) )
100 // Don't use the overlay mixer on Windows Vista
101 // It disables the desktop composition as soon as RenderFile is called
102 // also causes some other problems: video rendering is not reliable
104 // tdf#128057: IGraphBuilder::RenderFile seems to fail to handle file URIs properly when
105 // they contain encoded characters like "%23"; so pass system path in that case instead.
106 OUString
aFile(rURL
);
107 if (aFile
.startsWithIgnoreAsciiCase("file:"))
108 osl::FileBase::getSystemPathFromFileURL(rURL
, aFile
);
110 if( SUCCEEDED( mpGB
->RenderFile( o3tl::toW(aFile
.getStr()), nullptr ) ) &&
111 mpMC
.set(mpGB
, sal::systools::COM_QUERY
) &&
112 mpME
.set(mpGB
, sal::systools::COM_QUERY
) &&
113 mpMP
.set(mpGB
, sal::systools::COM_QUERY
) )
116 mpVW
.set(mpGB
, sal::systools::COM_QUERY
);
117 mpBV
.set(mpGB
, sal::systools::COM_QUERY
);
120 mpBA
.set(mpGB
, sal::systools::COM_QUERY
);
123 mpBA
->put_Volume( mnUnmutedVolume
);
138 const IVideoWindow
* Player::getVideoWindow() const
144 void Player::setNotifyWnd( HWND nNotifyWnd
)
148 mpME
->SetNotifyWindow( reinterpret_cast<OAHWND
>(nNotifyWnd
), WM_GRAPHNOTIFY
, reinterpret_cast< LONG_PTR
>( this ) );
152 void Player::processEvent()
155 LONG_PTR nParam1
, nParam2
;
157 while( mpME
&& SUCCEEDED( mpME
->GetEvent( &nCode
, &nParam1
, &nParam2
, 0 ) ) )
159 if( EC_COMPLETE
== nCode
)
168 setMediaTime( getDuration() );
173 mpME
->FreeEventParams( nCode
, nParam1
, nParam2
);
178 void SAL_CALL
Player::start( )
180 ::osl::MutexGuard
aGuard(m_aMutex
);
185 static WNDCLASSW
* mpWndClass
= nullptr;
188 mpWndClass
= new WNDCLASSW
;
190 memset( mpWndClass
, 0, sizeof( *mpWndClass
) );
191 mpWndClass
->hInstance
= GetModuleHandleW( nullptr );
192 mpWndClass
->cbWndExtra
= sizeof( DWORD
);
193 mpWndClass
->lpfnWndProc
= MediaPlayerWndProc_2
;
194 mpWndClass
->lpszClassName
= L
"com_sun_star_media_Sound_Player";
195 mpWndClass
->hbrBackground
= static_cast<HBRUSH
>(::GetStockObject( BLACK_BRUSH
));
196 mpWndClass
->hCursor
= ::LoadCursor( nullptr, IDC_ARROW
);
198 RegisterClassW( mpWndClass
);
202 mnFrameWnd
= CreateWindowW( mpWndClass
->lpszClassName
, nullptr,
205 nullptr, nullptr, mpWndClass
->hInstance
, nullptr );
208 ::ShowWindow(mnFrameWnd
, SW_HIDE
);
209 SetWindowLongPtrW( mnFrameWnd
, 0, reinterpret_cast<LONG_PTR
>(this) );
210 // mpVW->put_Owner( (OAHWND) mnFrameWnd );
211 setNotifyWnd( mnFrameWnd
);
221 void SAL_CALL
Player::stop( )
223 ::osl::MutexGuard
aGuard(m_aMutex
);
229 sal_Bool SAL_CALL
Player::isPlaying()
231 ::osl::MutexGuard
aGuard(m_aMutex
);
233 OAFilterState eFilterState
;
236 if( mpMC
&& SUCCEEDED( mpMC
->GetState( 10, &eFilterState
) ) )
237 bRet
= ( State_Running
== eFilterState
);
243 double SAL_CALL
Player::getDuration( )
245 ::osl::MutexGuard
aGuard(m_aMutex
);
247 REFTIME
aRefTime( 0.0 );
250 mpMP
->get_Duration( &aRefTime
);
256 void SAL_CALL
Player::setMediaTime( double fTime
)
258 ::osl::MutexGuard
aGuard(m_aMutex
);
262 const bool bPlaying
= isPlaying();
264 mpMP
->put_CurrentPosition( fTime
);
266 if( !bPlaying
&& mpMC
)
267 mpMC
->StopWhenReady();
272 double SAL_CALL
Player::getMediaTime( )
274 ::osl::MutexGuard
aGuard(m_aMutex
);
276 REFTIME
aRefTime( 0.0 );
279 mpMP
->get_CurrentPosition( &aRefTime
);
285 void SAL_CALL
Player::setPlaybackLoop( sal_Bool bSet
)
287 ::osl::MutexGuard
aGuard(m_aMutex
);
293 sal_Bool SAL_CALL
Player::isPlaybackLoop( )
295 ::osl::MutexGuard
aGuard(m_aMutex
);
301 void SAL_CALL
Player::setMute( sal_Bool bSet
)
303 ::osl::MutexGuard
aGuard(m_aMutex
);
305 if (mpBA
&& (mbMuted
!= static_cast<bool>(bSet
)))
308 mpBA
->put_Volume( mbMuted
? -10000 : mnUnmutedVolume
);
313 sal_Bool SAL_CALL
Player::isMute( )
315 ::osl::MutexGuard
aGuard(m_aMutex
);
321 void SAL_CALL
Player::setVolumeDB( sal_Int16 nVolumeDB
)
323 ::osl::MutexGuard
aGuard(m_aMutex
);
325 mnUnmutedVolume
= static_cast< long >( nVolumeDB
) * 100;
327 if( !mbMuted
&& mpBA
)
328 mpBA
->put_Volume( mnUnmutedVolume
);
332 sal_Int16 SAL_CALL
Player::getVolumeDB( )
334 ::osl::MutexGuard
aGuard(m_aMutex
);
336 return static_cast< sal_Int16
>( mnUnmutedVolume
/ 100 );
340 awt::Size SAL_CALL
Player::getPreferredPlayerWindowSize( )
342 ::osl::MutexGuard
aGuard(m_aMutex
);
344 awt::Size
aSize( 0, 0 );
348 long nWidth
= 0, nHeight
= 0;
350 mpBV
->GetVideoSize( &nWidth
, &nHeight
);
351 aSize
.Width
= nWidth
;
352 aSize
.Height
= nHeight
;
359 uno::Reference
< ::media::XPlayerWindow
> SAL_CALL
Player::createPlayerWindow( const uno::Sequence
< uno::Any
>& aArguments
)
361 ::osl::MutexGuard
aGuard(m_aMutex
);
363 uno::Reference
< ::media::XPlayerWindow
> xRet
;
364 awt::Size
aSize( getPreferredPlayerWindowSize() );
366 if( mpVW
&& aSize
.Width
> 0 && aSize
.Height
> 0 )
368 rtl::Reference
<::avmedia::win::Window
> pWindow
= new ::avmedia::win::Window( *this );
372 if( !pWindow
->create( aArguments
) )
380 uno::Reference
< media::XFrameGrabber
> SAL_CALL
Player::createFrameGrabber( )
382 uno::Reference
< media::XFrameGrabber
> xRet
;
384 if( !maURL
.isEmpty() )
386 rtl::Reference
<FrameGrabber
> pGrabber
= new FrameGrabber();
390 if( !pGrabber
->create( maURL
) )
398 OUString SAL_CALL
Player::getImplementationName( )
400 return AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME
;
404 sal_Bool SAL_CALL
Player::supportsService( const OUString
& ServiceName
)
406 return cppu::supportsService(this, ServiceName
);
410 uno::Sequence
< OUString
> SAL_CALL
Player::getSupportedServiceNames( )
412 return { AVMEDIA_WIN_PLAYER_SERVICENAME
};
415 } // namespace avmedia::win
418 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */