/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <objbase.h>
#include <strmif.h>
#include <control.h>
#include <uuids.h>
#include <evcode.h>
#include "player.hxx"
#include "framegrabber.hxx"
#include "window.hxx"
#include <cppuhelper/supportsservice.hxx>
#include <o3tl/char16_t2wchar_t.hxx>
#include <osl/file.hxx>
#include <rtl/ref.hxx>
constexpr OUStringLiteral AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME = u
"com.sun.star.comp.avmedia.Player_DirectX" ;
constexpr OUString AVMEDIA_WIN_PLAYER_SERVICENAME = u
"com.sun.star.media.Player_DirectX" _ustr;
using namespace ::com::sun::star;
namespace avmedia::win {
static LRESULT CALLBACK MediaPlayerWndProc_2( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nP
ar2 )
{
Player* pPlayer = reinterpret_cast <Player*>(::GetWindowLongPtrW( hWnd, 0 ));
bool bProcessed = true ;
if ( pPlayer )
{
switch ( nMsg )
{
case WM_GRAPHNOTIFY:
pPlayer->processEvent();
break ;
default :
bProcessed = false ;
break ;
}
}
else
bProcessed = false ;
return ( bProcessed ? 0 : DefWindowProcW( hWnd, nMsg, nPar1, nPar2 ) );
}
Player::Player() :
Player_BASE(m_aMutex),
sal::systools::CoInitializeGuard(COINIT_APARTMENTTHREADED, false ,
sal::systools::CoInitializeGuard::WhenFailed::NoThrow),
mnUnmutedVolume( 0 ),
mnFrameWnd( nullptr ),
mbMuted( false ),
mbLooping( false ),
mbAddWindow( true )
{
}
Player::~Player()
{
if ( mnFrameWnd )
::DestroyWindow( mnFrameWnd );
}
void SAL_CALL Player::disposing()
{
::osl::MutexGuard aGuard(m_aMutex);
stop();
if ( mpME )
mpME->SetNotifyWindow( 0, WM_GRAPHNOTIFY, 0);
}
bool Player::create( const OUString& rURL )
{
bool bRet = false ;
if ( SUCCEEDED(mpGB.CoCreateInstance(CLSID_FilterGraph, nullptr, CLSCTX_INPROC_SERVER)) )
{
// Don't use the overlay mixer on Windows Vista
// It disables the desktop composition as soon as RenderFile is called
// also causes some other problems: video rendering is not reliable
// tdf#128057: IGraphBuilder::RenderFile seems to fail to handle file URIs properly when
// they contain encoded characters like "%23"; so pass system path in that case instead.
OUString aFile(rURL);
if (aFile.startsWithIgnoreAsciiCase("file:" ))
osl::FileBase::getSystemPathFromFileURL(rURL, aFile);
if ( SUCCEEDED( mpGB->RenderFile( o3tl::toW(aFile.getStr()), nullptr ) ) &&
mpMC.set(mpGB, sal::systools::COM_QUERY) &&
mpME.set(mpGB, sal::systools::COM_QUERY) &&
mpMP.set(mpGB, sal::systools::COM_QUERY) )
{
// Video interfaces
mpVW.set(mpGB, sal::systools::COM_QUERY);
mpBV.set(mpGB, sal::systools::COM_QUERY);
// Audio interface
mpBA.set(mpGB, sal::systools::COM_QUERY);
if ( mpBA )
mpBA->put_Volume( mnUnmutedVolume );
bRet = true ;
}
}
if ( bRet )
maURL = rURL;
else
maURL.clear();
return bRet;
}
const IVideoWindow* Player::getVideoWindow() const
{
return mpVW;
}
void Player::setNotifyWnd( HWND nNotifyWnd )
{
mbAddWindow = false ;
if ( mpME )
mpME->SetNotifyWindow( reinterpret_cast <OAHWND>(nNotifyWnd), WM_GRAPHNOTIFY, reinterpret_cast < LONG_PTR>( this ) );
}
void Player::processEvent()
{
long nCode;
LONG_PTR nParam1, nParam2;
while ( mpME && SUCCEEDED( mpME->GetEvent( &nCode, &nParam1, &nParam2, 0 ) ) )
{
if ( EC_COMPLETE == nCode )
{
if ( mbLooping )
{
setMediaTime( 0.0 );
start();
}
else
{
setMediaTime( getDuration() );
stop();
}
}
mpME->FreeEventParams( nCode, nParam1, nParam2 );
}
}
void SAL_CALL Player::start( )
{
::osl::MutexGuard aGuard(m_aMutex);
if ( mpMC )
{
if ( mbAddWindow )
{
static WNDCLASSW* mpWndClass = nullptr;
if ( !mpWndClass )
{
mpWndClass = new WNDCLASSW;
memset( mpWndClass, 0, sizeof ( *mpWndClass ) );
mpWndClass->hInstance = GetModuleHandleW( nullptr );
mpWndClass->cbWndExtra = sizeof ( DWORD );
mpWndClass->lpfnWndProc = MediaPlayerWndProc_2;
mpWndClass->lpszClassName = L"com_sun_star_media_Sound_Player" ;
mpWndClass->hbrBackground = static_cast <HBRUSH>(::GetStockObject( BLACK_BRUSH ));
mpWndClass->hCursor = ::LoadCursor( nullptr, IDC_ARROW );
RegisterClassW( mpWndClass );
}
if ( !mnFrameWnd )
{
mnFrameWnd = CreateWindowW( mpWndClass->lpszClassName, nullptr,
0,
0, 0, 0, 0,
nullptr, nullptr, mpWndClass->hInstance, nullptr );
if ( mnFrameWnd )
{
::ShowWindow(mnFrameWnd, SW_HIDE);
SetWindowLongPtrW( mnFrameWnd, 0, reinterpret_cast <LONG_PTR>(this ) );
// mpVW->put_Owner( (OAHWND) mnFrameWnd );
setNotifyWnd( mnFrameWnd );
}
}
}
mpMC->Run();
}
}
void SAL_CALL Player::stop( )
{
::osl::MutexGuard aGuard(m_aMutex);
if ( mpMC )
mpMC->Stop();
}
sal_Bool SAL_CALL Player::isPlaying()
{
::osl::MutexGuard aGuard(m_aMutex);
OAFilterState eFilterState;
bool bRet = false ;
if ( mpMC && SUCCEEDED( mpMC->GetState( 10, &eFilterState ) ) )
bRet = ( State_Running == eFilterState );
return bRet;
}
double SAL_CALL Player::getDuration( )
{
::osl::MutexGuard aGuard(m_aMutex);
REFTIME aRefTime( 0.0 );
if ( mpMP )
mpMP->get_Duration( &aRefTime );
return aRefTime;
}
void SAL_CALL Player::setMediaTime( double fTime )
{
::osl::MutexGuard aGuard(m_aMutex);
if ( mpMP )
{
const bool bPlaying = isPlaying();
mpMP->put_CurrentPosition( fTime );
if ( !bPlaying && mpMC )
mpMC->StopWhenReady();
}
}
double SAL_CALL Player::getMediaTime( )
{
::osl::MutexGuard aGuard(m_aMutex);
REFTIME aRefTime( 0.0 );
if ( mpMP )
mpMP->get_CurrentPosition( &aRefTime );
return aRefTime;
}
void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet )
{
::osl::MutexGuard aGuard(m_aMutex);
mbLooping = bSet;
}
sal_Bool SAL_CALL Player::isPlaybackLoop( )
{
::osl::MutexGuard aGuard(m_aMutex);
return mbLooping;
}
void SAL_CALL Player::setMute( sal_Bool bSet )
{
::osl::MutexGuard aGuard(m_aMutex);
if (mpBA && (mbMuted != static_cast <bool >(bSet)))
{
mbMuted = bSet;
mpBA->put_Volume( mbMuted ? -10000 : mnUnmutedVolume );
}
}
sal_Bool SAL_CALL Player::isMute( )
{
::osl::MutexGuard aGuard(m_aMutex);
return mbMuted;
}
void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB )
{
::osl::MutexGuard aGuard(m_aMutex);
mnUnmutedVolume = static_cast < long >( nVolumeDB ) * 100;
if ( !mbMuted && mpBA )
mpBA->put_Volume( mnUnmutedVolume );
}
sal_Int16 SAL_CALL Player::getVolumeDB( )
{
::osl::MutexGuard aGuard(m_aMutex);
return static_cast < sal_Int16 >( mnUnmutedVolume / 100 );
}
awt::Size SAL_CALL Player::getPreferredPlayerWindowSize( )
{
::osl::MutexGuard aGuard(m_aMutex);
awt::Size aSize( 0, 0 );
if ( mpBV )
{
long nWidth = 0, nHeight = 0;
mpBV->GetVideoSize( &nWidth, &nHeight );
aSize.Width = nWidth;
aSize.Height = nHeight;
}
return aSize;
}
uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( const uno::Sequence< uno::Any >& aArguments )
{
::osl::MutexGuard aGuard(m_aMutex);
uno::Reference< ::media::XPlayerWindow > xRet;
awt::Size aSize( getPreferredPlayerWindowSize() );
if ( mpVW && aSize.Width > 0 && aSize.Height > 0 )
{
rtl::Reference<::avmedia::win::Window> pWindow = new ::avmedia::win::Window( *this );
xRet = pWindow;
if ( !pWindow->create( aArguments ) )
xRet.clear();
}
return xRet;
}
uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber( )
{
uno::Reference< media::XFrameGrabber > xRet;
if ( !maURL.isEmpty() )
{
rtl::Reference<FrameGrabber> pGrabber = new FrameGrabber();
xRet = pGrabber;
if ( !pGrabber->create( maURL ) )
xRet.clear();
}
return xRet;
}
OUString SAL_CALL Player::getImplementationName( )
{
return AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME;
}
sal_Bool SAL_CALL Player::supportsService( const OUString& ServiceName )
{
return cppu::supportsService(this , ServiceName);
}
uno::Sequence< OUString > SAL_CALL Player::getSupportedServiceNames( )
{
return { AVMEDIA_WIN_PLAYER_SERVICENAME };
}
} // namespace avmedia::win
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 C=97 H=99 G=97
¤ Dauer der Verarbeitung: 0.5 Sekunden
¤
*© Formatika GbR, Deutschland