diff options
Diffstat (limited to '')
-rw-r--r-- | avmedia/source/win/avmediawin.component | 25 | ||||
-rw-r--r-- | avmedia/source/win/framegrabber.cxx | 225 | ||||
-rw-r--r-- | avmedia/source/win/framegrabber.hxx | 57 | ||||
-rw-r--r-- | avmedia/source/win/interface.hxx | 120 | ||||
-rw-r--r-- | avmedia/source/win/manager.cxx | 77 | ||||
-rw-r--r-- | avmedia/source/win/manager.hxx | 51 | ||||
-rw-r--r-- | avmedia/source/win/player.cxx | 463 | ||||
-rw-r--r-- | avmedia/source/win/player.hxx | 119 | ||||
-rw-r--r-- | avmedia/source/win/wincommon.hxx | 44 | ||||
-rw-r--r-- | avmedia/source/win/window.cxx | 495 | ||||
-rw-r--r-- | avmedia/source/win/window.hxx | 114 | ||||
-rw-r--r-- | avmedia/source/win/winuno.cxx | 59 |
12 files changed, 1849 insertions, 0 deletions
diff --git a/avmedia/source/win/avmediawin.component b/avmedia/source/win/avmediawin.component new file mode 100644 index 000000000..3874439f4 --- /dev/null +++ b/avmedia/source/win/avmediawin.component @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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 . + --> + +<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@" + prefix="avmediawin" xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.avmedia.Manager_DirectX"> + <service name="com.sun.star.media.Manager_DirectX"/> + </implementation> +</component> diff --git a/avmedia/source/win/framegrabber.cxx b/avmedia/source/win/framegrabber.cxx new file mode 100644 index 000000000..21b5dede6 --- /dev/null +++ b/avmedia/source/win/framegrabber.cxx @@ -0,0 +1,225 @@ +/* -*- 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 <sal/config.h> + +#include <memory> + +#include <prewin.h> +#include <postwin.h> +#include <objbase.h> +#include <strmif.h> +#include <Amvideo.h> +#include "interface.hxx" +#include <uuids.h> + +#include "framegrabber.hxx" +#include "player.hxx" + +#include <cppuhelper/supportsservice.hxx> +#include <osl/file.hxx> +#include <tools/stream.hxx> +#include <vcl/graph.hxx> +#include <vcl/dibtools.hxx> +#include <o3tl/char16_t2wchar_t.hxx> + +#define AVMEDIA_WIN_FRAMEGRABBER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.FrameGrabber_DirectX" +#define AVMEDIA_WIN_FRAMEGRABBER_SERVICENAME "com.sun.star.media.FrameGrabber_DirectX" + +using namespace ::com::sun::star; + +namespace avmedia::win { + + +FrameGrabber::FrameGrabber( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) : + mxMgr( rxMgr ) +{ + ::CoInitializeEx( nullptr, COINIT_APARTMENTTHREADED ); +} + + +FrameGrabber::~FrameGrabber() +{ + ::CoUninitialize(); +} + +namespace { + +IMediaDet* implCreateMediaDet( const OUString& rURL ) +{ + IMediaDet* pDet = nullptr; + + if( SUCCEEDED( CoCreateInstance( CLSID_MediaDet, nullptr, CLSCTX_INPROC_SERVER, IID_IMediaDet, reinterpret_cast<void**>(&pDet) ) ) ) + { + OUString aLocalStr; + + if( osl::FileBase::getSystemPathFromFileURL( rURL, aLocalStr ) + == osl::FileBase::E_None ) + { + BSTR bstrFilename = SysAllocString(o3tl::toW(aLocalStr.getStr())); + if( !SUCCEEDED( pDet->put_Filename( bstrFilename ) ) ) + { + // Shouldn't we free this string unconditionally, not only in case of failure? + // I cannot find information why do we pass a newly allocated BSTR to the put_Filename + // and if it frees the string internally + SysFreeString(bstrFilename); + pDet->Release(); + pDet = nullptr; + } + } + } + + return pDet; +} + +} + +bool FrameGrabber::create( const OUString& rURL ) +{ + // just check if a MediaDet interface can be created with the given URL + IMediaDet* pDet = implCreateMediaDet( rURL ); + + if( pDet ) + { + maURL = rURL; + pDet->Release(); + pDet = nullptr; + } + else + maURL.clear(); + + return !maURL.isEmpty(); +} + + +uno::Reference< graphic::XGraphic > SAL_CALL FrameGrabber::grabFrame( double fMediaTime ) +{ + uno::Reference< graphic::XGraphic > xRet; + IMediaDet* pDet = implCreateMediaDet( maURL ); + + if( pDet ) + { + double fLength; + long nStreamCount; + bool bFound = false; + + if( SUCCEEDED( pDet->get_OutputStreams( &nStreamCount ) ) ) + { + for( long n = 0; ( n < nStreamCount ) && !bFound; ++n ) + { + GUID aMajorType; + + if( SUCCEEDED( pDet->put_CurrentStream( n ) ) && + SUCCEEDED( pDet->get_StreamType( &aMajorType ) ) && + ( aMajorType == MEDIATYPE_Video ) ) + { + bFound = true; + } + } + } + + if( bFound && + ( S_OK == pDet->get_StreamLength( &fLength ) ) && + ( fLength > 0.0 ) && ( fMediaTime >= 0.0 ) && ( fMediaTime <= fLength ) ) + { + AM_MEDIA_TYPE aMediaType; + long nWidth = 0, nHeight = 0, nSize = 0; + + if( SUCCEEDED( pDet->get_StreamMediaType( &aMediaType ) ) ) + { + if( ( aMediaType.formattype == FORMAT_VideoInfo ) && + ( aMediaType.cbFormat >= sizeof( VIDEOINFOHEADER ) ) ) + { + VIDEOINFOHEADER* pVih = reinterpret_cast< VIDEOINFOHEADER* >( aMediaType.pbFormat ); + + nWidth = pVih->bmiHeader.biWidth; + nHeight = pVih->bmiHeader.biHeight; + + if( nHeight < 0 ) + nHeight *= -1; + } + + if( aMediaType.cbFormat != 0 ) + { + ::CoTaskMemFree( aMediaType.pbFormat ); + aMediaType.cbFormat = 0; + aMediaType.pbFormat = nullptr; + } + + if( aMediaType.pUnk != nullptr ) + { + aMediaType.pUnk->Release(); + aMediaType.pUnk = nullptr; + } + } + + if( ( nWidth > 0 ) && ( nHeight > 0 ) && + SUCCEEDED( pDet->GetBitmapBits( 0, &nSize, nullptr, nWidth, nHeight ) ) && + ( nSize > 0 ) ) + { + auto pBuffer = std::make_unique<char[]>(nSize); + + try + { + if( SUCCEEDED( pDet->GetBitmapBits( fMediaTime, nullptr, pBuffer.get(), nWidth, nHeight ) ) ) + { + SvMemoryStream aMemStm( pBuffer.get(), nSize, StreamMode::READ | StreamMode::WRITE ); + Bitmap aBmp; + + if( ReadDIB(aBmp, aMemStm, false ) && !aBmp.IsEmpty() ) + { + const Graphic aGraphic( aBmp ); + xRet = aGraphic.GetXGraphic(); + } + } + } + catch( ... ) + { + } + } + } + + pDet->Release(); + } + + return xRet; +} + + +OUString SAL_CALL FrameGrabber::getImplementationName( ) +{ + return AVMEDIA_WIN_FRAMEGRABBER_IMPLEMENTATIONNAME; +} + + +sal_Bool SAL_CALL FrameGrabber::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + + +uno::Sequence< OUString > SAL_CALL FrameGrabber::getSupportedServiceNames( ) +{ + return { AVMEDIA_WIN_FRAMEGRABBER_SERVICENAME }; +} + +} // namespace avmedia::win + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/avmedia/source/win/framegrabber.hxx b/avmedia/source/win/framegrabber.hxx new file mode 100644 index 000000000..aa5b8945e --- /dev/null +++ b/avmedia/source/win/framegrabber.hxx @@ -0,0 +1,57 @@ +/* -*- 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 . + */ + +#pragma once + +#include "wincommon.hxx" +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/media/XFrameGrabber.hpp> + +struct IMediaDet; + +namespace avmedia::win { + +class FrameGrabber : public ::cppu::WeakImplHelper< css::media::XFrameGrabber, + css::lang::XServiceInfo > +{ +public: + + explicit FrameGrabber( const css::uno::Reference< css::lang::XMultiServiceFactory >& rxMgr ); + ~FrameGrabber() override; + + bool create( const OUString& rURL ); + + // XFrameGrabber + virtual css::uno::Reference< css::graphic::XGraphic > SAL_CALL grabFrame( double fMediaTime ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + +private: + + css::uno::Reference< css::lang::XMultiServiceFactory > mxMgr; + OUString maURL; +}; + +} // namespace avmedia::win + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/avmedia/source/win/interface.hxx b/avmedia/source/win/interface.hxx new file mode 100644 index 000000000..a52c6ab1f --- /dev/null +++ b/avmedia/source/win/interface.hxx @@ -0,0 +1,120 @@ +/* -*- 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 . + */ + +#pragma once + +extern "C" const CLSID CLSID_MediaDet; +extern "C" const IID IID_IMediaDet; +struct ISampleGrabber; + +struct +__declspec(uuid("65BD0710-24D2-4ff7-9324-ED2E5D3ABAFA")) __declspec(novtable) +IMediaDet : public IUnknown +{ +public: + virtual HRESULT __stdcall get_Filter( + IUnknown **pVal) = 0; + virtual HRESULT __stdcall put_Filter( + IUnknown *newVal) = 0; + virtual HRESULT __stdcall get_OutputStreams( + long *pVal) = 0; + virtual HRESULT __stdcall get_CurrentStream( + long *pVal) = 0; + virtual HRESULT __stdcall put_CurrentStream( + long newVal) = 0; + virtual HRESULT __stdcall get_StreamType( + GUID *pVal) = 0; + virtual HRESULT __stdcall get_StreamTypeB( + BSTR *pVal) = 0; + virtual HRESULT __stdcall get_StreamLength( + double *pVal) = 0; + virtual HRESULT __stdcall get_Filename( + BSTR *pVal) = 0; + virtual HRESULT __stdcall put_Filename( + BSTR newVal) = 0; + virtual HRESULT __stdcall GetBitmapBits( + double StreamTime, + long *pBufferSize, + char *pBuffer, + long Width, + long Height) = 0; + virtual HRESULT __stdcall WriteBitmapBits( + double StreamTime, + long Width, + long Height, + BSTR Filename) = 0; + virtual HRESULT __stdcall get_StreamMediaType( + AM_MEDIA_TYPE *pVal) = 0; + virtual HRESULT __stdcall GetSampleGrabber( + ISampleGrabber **ppVal) = 0; + virtual HRESULT __stdcall get_FrameRate( + double *pVal) = 0; + virtual HRESULT __stdcall EnterBitmapGrabMode( + double SeekTime) = 0; + +protected: + ~IMediaDet() {} +}; + +extern "C" const IID IID_ISampleGrabberCB; +struct +__declspec(uuid("0579154A-2B53-4994-B0D0-E773148EFF85")) __declspec(novtable) +ISampleGrabberCB : public IUnknown +{ +public: + virtual HRESULT __stdcall SampleCB( + double SampleTime, + IMediaSample *pSample) = 0; + virtual HRESULT __stdcall BufferCB( + double SampleTime, + BYTE *pBuffer, + long BufferLen) = 0; + +protected: + ~ISampleGrabberCB() {} +}; + +extern "C" const IID IID_ISampleGrabber; +struct +__declspec(uuid("6B652FFF-11FE-4fce-92AD-0266B5D7C78F")) __declspec(novtable) +ISampleGrabber : public IUnknown +{ +public: + virtual HRESULT __stdcall SetOneShot( + BOOL OneShot) = 0; + virtual HRESULT __stdcall SetMediaType( + const AM_MEDIA_TYPE *pType) = 0; + virtual HRESULT __stdcall GetConnectedMediaType( + AM_MEDIA_TYPE *pType) = 0; + virtual HRESULT __stdcall SetBufferSamples( + BOOL BufferThem) = 0; + virtual HRESULT __stdcall GetCurrentBuffer( + long *pBufferSize, + long *pBuffer) = 0; + virtual HRESULT __stdcall GetCurrentSample( + IMediaSample **ppSample) = 0; + virtual HRESULT __stdcall SetCallback( + ISampleGrabberCB *pCallback, + long WhichMethodToCallback) = 0; + +protected: + ~ISampleGrabber() {} +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/avmedia/source/win/manager.cxx b/avmedia/source/win/manager.cxx new file mode 100644 index 000000000..3615850a7 --- /dev/null +++ b/avmedia/source/win/manager.cxx @@ -0,0 +1,77 @@ +/* -*- 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 "manager.hxx" +#include "player.hxx" + +#include <cppuhelper/supportsservice.hxx> +#include <tools/urlobj.hxx> + +#define AVMEDIA_WIN_MANAGER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Manager_DirectX" +#define AVMEDIA_WIN_MANAGER_SERVICENAME "com.sun.star.media.Manager" + +using namespace ::com::sun::star; + +namespace avmedia::win { + +Manager::Manager( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) : + mxMgr( rxMgr ) +{ +} + + +Manager::~Manager() +{ +} + + +uno::Reference< media::XPlayer > SAL_CALL Manager::createPlayer( const OUString& rURL ) +{ + Player* pPlayer( new Player( mxMgr ) ); + uno::Reference< media::XPlayer > xRet( pPlayer ); + const INetURLObject aURL( rURL ); + + if( !pPlayer->create( aURL.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous ) ) ) + xRet.clear(); + + return xRet; +} + + +OUString SAL_CALL Manager::getImplementationName( ) +{ + return AVMEDIA_WIN_MANAGER_IMPLEMENTATIONNAME; +} + + +sal_Bool SAL_CALL Manager::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + + +uno::Sequence< OUString > SAL_CALL Manager::getSupportedServiceNames( ) +{ + return { AVMEDIA_WIN_MANAGER_SERVICENAME }; +} + +} // namespace avmedia::win + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/avmedia/source/win/manager.hxx b/avmedia/source/win/manager.hxx new file mode 100644 index 000000000..77d1ce6ef --- /dev/null +++ b/avmedia/source/win/manager.hxx @@ -0,0 +1,51 @@ +/* -*- 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 . + */ + +#pragma once + +#include "wincommon.hxx" +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/media/XManager.hpp> + + +namespace avmedia::win { + +class Manager : public ::cppu::WeakImplHelper< css::media::XManager, + css::lang::XServiceInfo > +{ +public: + + explicit Manager( const css::uno::Reference< css::lang::XMultiServiceFactory >& rxMgr ); + ~Manager() override; + + // XManager + virtual css::uno::Reference< css::media::XPlayer > SAL_CALL createPlayer( const OUString& aURL ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +private: + + css::uno::Reference< css::lang::XMultiServiceFactory > mxMgr; +}; + +} // namespace avmedia::win + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/avmedia/source/win/player.cxx b/avmedia/source/win/player.cxx new file mode 100644 index 000000000..8e08d9e53 --- /dev/null +++ b/avmedia/source/win/player.cxx @@ -0,0 +1,463 @@ +/* -*- 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> + +#define AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Player_DirectX" +#define AVMEDIA_WIN_PLAYER_SERVICENAME "com.sun.star.media.Player_DirectX" + +using namespace ::com::sun::star; + +namespace avmedia::win { + +static LRESULT CALLBACK MediaPlayerWndProc_2( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nPar2 ) +{ + 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( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) : + Player_BASE(m_aMutex), + mxMgr( rxMgr ), + mpGB( nullptr ), + mpOMF( nullptr ), + mpMC( nullptr ), + mpME( nullptr ), + mpMS( nullptr ), + mpMP( nullptr ), + mpBA( nullptr ), + mpBV( nullptr ), + mpVW( nullptr ), + mpEV( nullptr ), + mnUnmutedVolume( 0 ), + mnFrameWnd( nullptr ), + mbMuted( false ), + mbLooping( false ), + mbAddWindow( true ) +{ + ::CoInitializeEx( nullptr, COINIT_APARTMENTTHREADED ); +} + + +Player::~Player() +{ + if( mnFrameWnd ) + ::DestroyWindow( mnFrameWnd ); + + ::CoUninitialize(); +} + + +void SAL_CALL Player::disposing() +{ + ::osl::MutexGuard aGuard(m_aMutex); + stop(); + if( mpBA ) + mpBA->Release(); + + if( mpBV ) + mpBV->Release(); + + if( mpVW ) + mpVW->Release(); + + if( mpMP ) + mpMP->Release(); + + if( mpMS ) + mpMS->Release(); + + if( mpME ) + { + mpME->SetNotifyWindow( 0, WM_GRAPHNOTIFY, 0); + mpME->Release(); + } + + if( mpMC ) + mpMC->Release(); + + if( mpEV ) + mpEV->Release(); + + if( mpOMF ) + mpOMF->Release(); + + if( mpGB ) + mpGB->Release(); +} + + +bool Player::create( const OUString& rURL ) +{ + HRESULT hR; + bool bRet = false; + + if( SUCCEEDED( hR = CoCreateInstance( CLSID_FilterGraph, nullptr, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, reinterpret_cast<void**>(&mpGB) ) ) ) + { + // 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( hR = mpGB->RenderFile( o3tl::toW(aFile.getStr()), nullptr ) ) && + SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaControl, reinterpret_cast<void**>(&mpMC) ) ) && + SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaEventEx, reinterpret_cast<void**>(&mpME) ) ) && + SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaSeeking, reinterpret_cast<void**>(&mpMS) ) ) && + SUCCEEDED( hR = mpGB->QueryInterface( IID_IMediaPosition, reinterpret_cast<void**>(&mpMP) ) ) ) + { + // Video interfaces + mpGB->QueryInterface( IID_IVideoWindow, reinterpret_cast<void**>(&mpVW) ); + mpGB->QueryInterface( IID_IBasicVideo, reinterpret_cast<void**>(&mpBV) ); + + // Audio interface + mpGB->QueryInterface( IID_IBasicAudio, reinterpret_cast<void**>(&mpBA) ); + + 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 ) ); +} + + +long 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 ); + } + + return 0; +} + + +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 ) + { + ::avmedia::win::Window* pWindow = new ::avmedia::win::Window( mxMgr, *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() ) + { + FrameGrabber* pGrabber = new FrameGrabber( mxMgr ); + + 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: */ diff --git a/avmedia/source/win/player.hxx b/avmedia/source/win/player.hxx new file mode 100644 index 000000000..370851368 --- /dev/null +++ b/avmedia/source/win/player.hxx @@ -0,0 +1,119 @@ +/* -*- 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 . + */ + +#pragma once + +#include <sal/config.h> + +#include <WinDef.h> + +#include "wincommon.hxx" + +#include <com/sun/star/media/XPlayer.hpp> + +#include <cppuhelper/compbase.hxx> +#include <cppuhelper/basemutex.hxx> + +struct IGraphBuilder; +struct IBaseFilter; +struct IMediaControl; +struct IMediaEventEx; +struct IMediaSeeking; +struct IMediaPosition; +struct IBasicAudio; +struct IBasicVideo; +struct IVideoWindow; +struct IDDrawExclModeVideo; +struct IDirectDraw; +struct IDirectDrawSurface; + +namespace avmedia::win { + +typedef ::cppu::WeakComponentImplHelper< css::media::XPlayer, + css::lang::XServiceInfo > Player_BASE; + + +class Player : public cppu::BaseMutex, + public Player_BASE +{ +public: + + explicit Player( const css::uno::Reference< css::lang::XMultiServiceFactory >& rxMgr ); + ~Player() override; + + bool create( const OUString& rURL ); + + void setNotifyWnd( HWND nNotifyWnd ); + long processEvent(); + + const IVideoWindow* getVideoWindow() const; + + // XPlayer + virtual void SAL_CALL start( ) override; + virtual void SAL_CALL stop( ) override; + virtual sal_Bool SAL_CALL isPlaying( ) override; + virtual double SAL_CALL getDuration( ) override; + virtual void SAL_CALL setMediaTime( double fTime ) override; + virtual double SAL_CALL getMediaTime( ) override; + virtual void SAL_CALL setPlaybackLoop( sal_Bool bSet ) override; + virtual sal_Bool SAL_CALL isPlaybackLoop( ) override; + virtual void SAL_CALL setMute( sal_Bool bSet ) override; + virtual sal_Bool SAL_CALL isMute( ) override; + virtual void SAL_CALL setVolumeDB( sal_Int16 nVolumeDB ) override; + virtual sal_Int16 SAL_CALL getVolumeDB( ) override; + virtual css::awt::Size SAL_CALL getPreferredPlayerWindowSize( ) override; + virtual css::uno::Reference< css::media::XPlayerWindow > SAL_CALL createPlayerWindow( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + virtual css::uno::Reference< css::media::XFrameGrabber > SAL_CALL createFrameGrabber( ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + // ::cppu::OComponentHelper + virtual void SAL_CALL disposing() override; + +private: + + css::uno::Reference< css::lang::XMultiServiceFactory > mxMgr; + + OUString maURL; + IGraphBuilder* mpGB; + IBaseFilter* mpOMF; + IMediaControl* mpMC; + IMediaEventEx* mpME; + IMediaSeeking* mpMS; + IMediaPosition* mpMP; + IBasicAudio* mpBA; + IBasicVideo* mpBV; + IVideoWindow* mpVW; + IDDrawExclModeVideo* mpEV; + long mnUnmutedVolume; + HWND mnFrameWnd; + bool mbMuted; + bool mbLooping; + bool mbAddWindow; + + void ImplLayoutVideoWindow(); +}; + +} // namespace avmedia::win + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/avmedia/source/win/wincommon.hxx b/avmedia/source/win/wincommon.hxx new file mode 100644 index 000000000..f0277e169 --- /dev/null +++ b/avmedia/source/win/wincommon.hxx @@ -0,0 +1,44 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_AVMEDIA_SOURCE_WIN_WINCOMMON_HXX +#define INCLUDED_AVMEDIA_SOURCE_WIN_WINCOMMON_HXX + +#include <osl/mutex.hxx> +#include <rtl/ustring.hxx> +#include <tools/stream.hxx> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/factory.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/awt/KeyModifier.hpp> +#include <com/sun/star/awt/MouseButton.hpp> +#include <com/sun/star/media/XManager.hpp> + +#define WM_GRAPHNOTIFY (WM_USER + 567) + +#endif // INCLUDED_AVMEDIA_SOURCE_WIN_WINCOMMON_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/avmedia/source/win/window.cxx b/avmedia/source/win/window.cxx new file mode 100644 index 000000000..995ddd92c --- /dev/null +++ b/avmedia/source/win/window.cxx @@ -0,0 +1,495 @@ +/* -*- 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 <dshow.h> + +#include <com/sun/star/awt/SystemPointer.hpp> +#include <cppuhelper/supportsservice.hxx> + +#include "window.hxx" +#include "player.hxx" + +#define AVMEDIA_WIN_WINDOW_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Window_DirectX" +#define AVMEDIA_WIN_WINDOW_SERVICENAME "com.sun.star.media.Window_DirectX" + +using namespace ::com::sun::star; + +namespace avmedia::win { + +static LRESULT CALLBACK MediaPlayerWndProc( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nPar2 ) +{ + Window* pWindow = reinterpret_cast<Window*>(GetWindowLongPtrW( hWnd, 0 )); + bool bProcessed = true; + + if( pWindow ) + { + switch( nMsg ) + { + case WM_SETCURSOR: + pWindow->updatePointer(); + break; + + case WM_GRAPHNOTIFY: + pWindow->processGraphEvent(); + break; + + case WM_MOUSEMOVE: + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + PostMessage(pWindow->getParentWnd(), nMsg, nPar1, nPar2); + break; + + case WM_SETFOCUS: + { + const awt::FocusEvent aUNOEvt; + pWindow->fireSetFocusEvent( aUNOEvt ); + } + break; + + default: + bProcessed = false; + break; + } + } + else + bProcessed = false; + + return( bProcessed ? 0 : DefWindowProcW( hWnd, nMsg, nPar1, nPar2 ) ); +} + +static WNDCLASSW* lcl_getWndClass() +{ + WNDCLASSW* s_pWndClass = new WNDCLASSW; + + memset( s_pWndClass, 0, sizeof( *s_pWndClass ) ); + s_pWndClass->hInstance = GetModuleHandleW( nullptr ); + s_pWndClass->cbWndExtra = sizeof( DWORD_PTR ); + s_pWndClass->lpfnWndProc = MediaPlayerWndProc; + s_pWndClass->lpszClassName = L"com_sun_star_media_PlayerWnd"; + s_pWndClass->hbrBackground = static_cast<HBRUSH>(::GetStockObject( BLACK_BRUSH )); + s_pWndClass->hCursor = ::LoadCursor( nullptr, IDC_ARROW ); + + RegisterClassW( s_pWndClass ); + + return s_pWndClass; +} + +Window::Window( const uno::Reference< lang::XMultiServiceFactory >& rxMgr, Player& rPlayer ) : + mxMgr( rxMgr ), + maListeners( maMutex ), + meZoomLevel( media::ZoomLevel_NOT_AVAILABLE ), + mrPlayer( rPlayer ), + mnFrameWnd( nullptr ), + mnParentWnd( nullptr ), + mnPointerType( awt::SystemPointer::ARROW ) +{ +} + +Window::~Window() +{ + if( mnFrameWnd ) + ::DestroyWindow( mnFrameWnd ); +} + +void Window::ImplLayoutVideoWindow() +{ + if( media::ZoomLevel_NOT_AVAILABLE != meZoomLevel ) + { + awt::Size aPrefSize( mrPlayer.getPreferredPlayerWindowSize() ); + awt::Rectangle aRect = getPosSize(); + int nW = aRect.Width, nH = aRect.Height; + int nVideoW = nW, nVideoH = nH; + int nX = 0, nY = 0, nWidth = 0, nHeight = 0; + bool bDone = false, bZoom = false; + + if( media::ZoomLevel_ORIGINAL == meZoomLevel ) + { + bZoom = true; + } + else if( media::ZoomLevel_ZOOM_1_TO_4 == meZoomLevel ) + { + aPrefSize.Width >>= 2; + aPrefSize.Height >>= 2; + bZoom = true; + } + else if( media::ZoomLevel_ZOOM_1_TO_2 == meZoomLevel ) + { + aPrefSize.Width >>= 1; + aPrefSize.Height >>= 1; + bZoom = true; + } + else if( media::ZoomLevel_ZOOM_2_TO_1 == meZoomLevel ) + { + aPrefSize.Width <<= 1; + aPrefSize.Height <<= 1; + bZoom = true; + } + else if( media::ZoomLevel_ZOOM_4_TO_1 == meZoomLevel ) + { + aPrefSize.Width <<= 2; + aPrefSize.Height <<= 2; + bZoom = true; + } + else if( media::ZoomLevel_FIT_TO_WINDOW == meZoomLevel ) + { + nWidth = nVideoW; + nHeight = nVideoH; + bDone = true; + } + + if( bZoom ) + { + if( ( aPrefSize.Width <= nVideoW ) && ( aPrefSize.Height <= nVideoH ) ) + { + nX = ( nVideoW - aPrefSize.Width ) >> 1; + nY = ( nVideoH - aPrefSize.Height ) >> 1; + nWidth = aPrefSize.Width; + nHeight = aPrefSize.Height; + bDone = true; + } + } + + if( !bDone ) + { + if( aPrefSize.Width > 0 && aPrefSize.Height > 0 && nVideoW > 0 && nVideoH > 0 ) + { + double fPrefWH = static_cast<double>(aPrefSize.Width) / aPrefSize.Height; + + if( fPrefWH < ( static_cast<double>(nVideoW) / nVideoH ) ) + nVideoW = static_cast<int>( nVideoH * fPrefWH ); + else + nVideoH = static_cast<int>( nVideoW / fPrefWH ); + + nX = ( nW - nVideoW ) >> 1; + nY = ( nH - nVideoH ) >> 1; + nWidth = nVideoW; + nHeight = nVideoH; + } + else + nX = nY = nWidth = nHeight = 0; + } + + IVideoWindow* pVideoWindow = const_cast< IVideoWindow* >( mrPlayer.getVideoWindow() ); + + if( pVideoWindow ) + pVideoWindow->SetWindowPosition( nX, nY, nWidth, nHeight ); + } +} + +bool Window::create( const uno::Sequence< uno::Any >& rArguments ) +{ + IVideoWindow* pVideoWindow = const_cast< IVideoWindow* >( mrPlayer.getVideoWindow() ); + static WNDCLASSW* mpWndClass = lcl_getWndClass(); + + if( !mnFrameWnd && pVideoWindow && mpWndClass ) + { + awt::Rectangle aRect; + sal_IntPtr nWnd; + + rArguments[ 0 ] >>= nWnd; + rArguments[ 1 ] >>= aRect; + + mnParentWnd = reinterpret_cast<HWND>(nWnd); + + mnFrameWnd = CreateWindowW( mpWndClass->lpszClassName, nullptr, + WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, + aRect.X, aRect.Y, aRect.Width, aRect.Height, + mnParentWnd, nullptr, mpWndClass->hInstance, nullptr ); + + if( mnFrameWnd ) + { + SetWindowLongPtrW( mnFrameWnd, 0, reinterpret_cast<LONG_PTR>(this) ); + + pVideoWindow->put_Owner( reinterpret_cast<OAHWND>(mnFrameWnd) ); + pVideoWindow->put_MessageDrain( reinterpret_cast<OAHWND>(mnFrameWnd) ); + pVideoWindow->put_WindowStyle( WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN ); + + mrPlayer.setNotifyWnd( mnFrameWnd ); + + meZoomLevel = media::ZoomLevel_FIT_TO_WINDOW; + ImplLayoutVideoWindow(); + } + } + + return( mnFrameWnd != nullptr ); +} + +void Window::processGraphEvent() +{ + mrPlayer.processEvent(); +} + +void Window::updatePointer() +{ + LPCTSTR pCursorName; + + switch( mnPointerType ) + { + case awt::SystemPointer::CROSS: pCursorName = IDC_CROSS; break; + case awt::SystemPointer::MOVE: pCursorName = IDC_SIZEALL; break; + case awt::SystemPointer::WAIT: pCursorName = IDC_WAIT; break; + + default: + pCursorName = IDC_ARROW; + break; + } + + SetCursor( LoadCursor( nullptr, pCursorName ) ); +} + +void SAL_CALL Window::update( ) +{ + ::RedrawWindow( mnFrameWnd, nullptr, nullptr, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE ); +} + +sal_Bool SAL_CALL Window::setZoomLevel( media::ZoomLevel eZoomLevel ) +{ + bool bRet = false; + + if( media::ZoomLevel_NOT_AVAILABLE != meZoomLevel && + media::ZoomLevel_NOT_AVAILABLE != eZoomLevel ) + { + if( eZoomLevel != meZoomLevel ) + { + meZoomLevel = eZoomLevel; + ImplLayoutVideoWindow(); + } + + bRet = true; + } + + return bRet; +} + +media::ZoomLevel SAL_CALL Window::getZoomLevel( ) +{ + return meZoomLevel; +} + +void SAL_CALL Window::setPointerType( sal_Int32 nPointerType ) +{ + mnPointerType = nPointerType; +} + +void SAL_CALL Window::setPosSize( sal_Int32 X, sal_Int32 Y, sal_Int32 Width, sal_Int32 Height, sal_Int16 ) +{ + if( mnFrameWnd ) + { + ::SetWindowPos( mnFrameWnd, HWND_TOP, X, Y, Width, Height, 0 ); + ImplLayoutVideoWindow(); + } +} + +awt::Rectangle SAL_CALL Window::getPosSize() +{ + awt::Rectangle aRet; + + if( mnFrameWnd ) + { + ::RECT aWndRect; + + if( ::GetClientRect( mnFrameWnd, &aWndRect ) ) + { + aRet.X = aWndRect.left; + aRet.Y = aWndRect.top; + aRet.Width = aWndRect.right - aWndRect.left + 1; + aRet.Height = aWndRect.bottom - aWndRect.top + 1; + } + } + + return aRet; +} + +void SAL_CALL Window::setVisible( sal_Bool bVisible ) +{ + if( mnFrameWnd ) + { + IVideoWindow* pVideoWindow = const_cast< IVideoWindow* >( mrPlayer.getVideoWindow() ); + + if( pVideoWindow ) + pVideoWindow->put_Visible( bVisible ? OATRUE : OAFALSE ); + + ::ShowWindow( mnFrameWnd, bVisible ? SW_SHOW : SW_HIDE ); + } +} + +void SAL_CALL Window::setEnable( sal_Bool bEnable ) +{ + if( mnFrameWnd ) + ::EnableWindow( mnFrameWnd, bEnable ); +} + +void SAL_CALL Window::setFocus( ) +{ + if( mnFrameWnd ) + ::SetFocus( mnFrameWnd ); +} + +void SAL_CALL Window::addWindowListener( const uno::Reference< awt::XWindowListener >& xListener ) +{ + maListeners.addInterface( cppu::UnoType<decltype(xListener)>::get(), xListener ); +} + +void SAL_CALL Window::removeWindowListener( const uno::Reference< awt::XWindowListener >& xListener ) +{ + maListeners.removeInterface( cppu::UnoType<decltype(xListener)>::get(), xListener ); +} + +void SAL_CALL Window::addFocusListener( const uno::Reference< awt::XFocusListener >& xListener ) +{ + maListeners.addInterface( cppu::UnoType<decltype(xListener)>::get(), xListener ); +} + +void SAL_CALL Window::removeFocusListener( const uno::Reference< awt::XFocusListener >& xListener ) +{ + maListeners.removeInterface( cppu::UnoType<decltype(xListener)>::get(), xListener ); +} + +void SAL_CALL Window::addKeyListener( const uno::Reference< awt::XKeyListener >& xListener ) +{ + maListeners.addInterface( cppu::UnoType<decltype(xListener)>::get(), xListener ); +} + +void SAL_CALL Window::removeKeyListener( const uno::Reference< awt::XKeyListener >& xListener ) +{ + maListeners.removeInterface( cppu::UnoType<decltype(xListener)>::get(), xListener ); +} + +void SAL_CALL Window::addMouseListener( const uno::Reference< awt::XMouseListener >& xListener ) +{ + maListeners.addInterface( cppu::UnoType<decltype(xListener)>::get(), xListener ); +} + +void SAL_CALL Window::removeMouseListener( const uno::Reference< awt::XMouseListener >& xListener ) +{ + maListeners.removeInterface( cppu::UnoType<decltype(xListener)>::get(), xListener ); +} + +void SAL_CALL Window::addMouseMotionListener( const uno::Reference< awt::XMouseMotionListener >& xListener ) +{ + maListeners.addInterface( cppu::UnoType<decltype(xListener)>::get(), xListener ); +} + +void SAL_CALL Window::removeMouseMotionListener( const uno::Reference< awt::XMouseMotionListener >& xListener ) +{ + maListeners.removeInterface( cppu::UnoType<decltype(xListener)>::get(), xListener ); +} + +void SAL_CALL Window::addPaintListener( const uno::Reference< awt::XPaintListener >& xListener ) +{ + maListeners.addInterface( cppu::UnoType<decltype(xListener)>::get(), xListener ); +} + +void SAL_CALL Window::removePaintListener( const uno::Reference< awt::XPaintListener >& xListener ) +{ + maListeners.removeInterface( cppu::UnoType<decltype(xListener)>::get(), xListener ); +} + +void SAL_CALL Window::dispose( ) +{ +} + +void SAL_CALL Window::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) +{ + maListeners.addInterface( cppu::UnoType<decltype(xListener)>::get(), xListener ); +} + +void SAL_CALL Window::removeEventListener( const uno::Reference< lang::XEventListener >& xListener ) +{ + maListeners.removeInterface( cppu::UnoType<decltype(xListener)>::get(), xListener ); +} + +void Window::fireMousePressedEvent( const css::awt::MouseEvent& rEvt ) +{ + ::cppu::OInterfaceContainerHelper* pContainer = maListeners.getContainer( cppu::UnoType<awt::XMouseListener>::get()); + + if( pContainer ) + { + ::cppu::OInterfaceIteratorHelper aIter( *pContainer ); + + while( aIter.hasMoreElements() ) + uno::Reference< awt::XMouseListener >( aIter.next(), uno::UNO_QUERY_THROW )->mousePressed( rEvt ); + } +} + +void Window::fireMouseReleasedEvent( const css::awt::MouseEvent& rEvt ) +{ + ::cppu::OInterfaceContainerHelper* pContainer = maListeners.getContainer( cppu::UnoType<awt::XMouseListener>::get()); + + if( pContainer ) + { + ::cppu::OInterfaceIteratorHelper aIter( *pContainer ); + + while( aIter.hasMoreElements() ) + uno::Reference< awt::XMouseListener >( aIter.next(), uno::UNO_QUERY_THROW )->mouseReleased( rEvt ); + } +} + +void Window::fireMouseMovedEvent( const css::awt::MouseEvent& rEvt ) +{ + ::cppu::OInterfaceContainerHelper* pContainer = maListeners.getContainer( cppu::UnoType<awt::XMouseMotionListener>::get()); + + if( pContainer ) + { + ::cppu::OInterfaceIteratorHelper aIter( *pContainer ); + + while( aIter.hasMoreElements() ) + uno::Reference< awt::XMouseMotionListener >( aIter.next(), uno::UNO_QUERY_THROW )->mouseMoved( rEvt ); + } +} + +void Window::fireSetFocusEvent( const css::awt::FocusEvent& rEvt ) +{ + ::cppu::OInterfaceContainerHelper* pContainer = maListeners.getContainer( cppu::UnoType<awt::XFocusListener>::get()); + + if( pContainer ) + { + ::cppu::OInterfaceIteratorHelper aIter( *pContainer ); + + while( aIter.hasMoreElements() ) + uno::Reference< awt::XFocusListener >( aIter.next(), uno::UNO_QUERY_THROW )->focusGained( rEvt ); + } +} + +OUString SAL_CALL Window::getImplementationName( ) +{ + return AVMEDIA_WIN_WINDOW_IMPLEMENTATIONNAME; +} + +sal_Bool SAL_CALL Window::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +uno::Sequence< OUString > SAL_CALL Window::getSupportedServiceNames( ) +{ + return { AVMEDIA_WIN_WINDOW_SERVICENAME }; +} + +} // namespace avmedia::win + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/avmedia/source/win/window.hxx b/avmedia/source/win/window.hxx new file mode 100644 index 000000000..a947c1717 --- /dev/null +++ b/avmedia/source/win/window.hxx @@ -0,0 +1,114 @@ +/* -*- 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 . + */ + +#pragma once + +#include <sal/config.h> + +#include <WinDef.h> + +#include "wincommon.hxx" +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/interfacecontainer.h> + +#include <com/sun/star/media/XPlayerWindow.hpp> + +struct IVideoWindow; + +namespace avmedia::win { + +class Player; + + +class Window : public ::cppu::WeakImplHelper< css::media::XPlayerWindow, + css::lang::XServiceInfo > +{ +public: + + Window( const css::uno::Reference< css::lang::XMultiServiceFactory >& rxMgr, + Player& rPlayer ); + ~Window() override; + + bool create( const css::uno::Sequence< css::uno::Any >& aArguments ); + void processGraphEvent(); + void updatePointer(); + + // XPlayerWindow + virtual void SAL_CALL update( ) override; + virtual sal_Bool SAL_CALL setZoomLevel( css::media::ZoomLevel ZoomLevel ) override; + virtual css::media::ZoomLevel SAL_CALL getZoomLevel( ) override; + virtual void SAL_CALL setPointerType( sal_Int32 nPointerType ) override; + + // XWindow + virtual void SAL_CALL setPosSize( sal_Int32 X, sal_Int32 Y, sal_Int32 Width, sal_Int32 Height, sal_Int16 Flags ) override; + virtual css::awt::Rectangle SAL_CALL getPosSize( ) override; + virtual void SAL_CALL setVisible( sal_Bool Visible ) override; + virtual void SAL_CALL setEnable( sal_Bool Enable ) override; + virtual void SAL_CALL setFocus( ) override; + virtual void SAL_CALL addWindowListener( const css::uno::Reference< css::awt::XWindowListener >& xListener ) override; + virtual void SAL_CALL removeWindowListener( const css::uno::Reference< css::awt::XWindowListener >& xListener ) override; + virtual void SAL_CALL addFocusListener( const css::uno::Reference< css::awt::XFocusListener >& xListener ) override; + virtual void SAL_CALL removeFocusListener( const css::uno::Reference< css::awt::XFocusListener >& xListener ) override; + virtual void SAL_CALL addKeyListener( const css::uno::Reference< css::awt::XKeyListener >& xListener ) override; + virtual void SAL_CALL removeKeyListener( const css::uno::Reference< css::awt::XKeyListener >& xListener ) override; + virtual void SAL_CALL addMouseListener( const css::uno::Reference< css::awt::XMouseListener >& xListener ) override; + virtual void SAL_CALL removeMouseListener( const css::uno::Reference< css::awt::XMouseListener >& xListener ) override; + virtual void SAL_CALL addMouseMotionListener( const css::uno::Reference< css::awt::XMouseMotionListener >& xListener ) override; + virtual void SAL_CALL removeMouseMotionListener( const css::uno::Reference< css::awt::XMouseMotionListener >& xListener ) override; + virtual void SAL_CALL addPaintListener( const css::uno::Reference< css::awt::XPaintListener >& xListener ) override; + virtual void SAL_CALL removePaintListener( const css::uno::Reference< css::awt::XPaintListener >& xListener ) override; + + // XComponent + virtual void SAL_CALL dispose( ) override; + virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override; + virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + +public: + + void fireMousePressedEvent( const css::awt::MouseEvent& rEvt ); + void fireMouseReleasedEvent( const css::awt::MouseEvent& rEvt ); + void fireMouseMovedEvent( const css::awt::MouseEvent& rEvt ); + void fireKeyPressedEvent( const css::awt::KeyEvent& rEvt ); + void fireKeyReleasedEvent( const css::awt::KeyEvent& rEvt ); + void fireSetFocusEvent( const css::awt::FocusEvent& rEvt ); + HWND getParentWnd() const { return mnParentWnd; } + +private: + + css::uno::Reference< css::lang::XMultiServiceFactory > mxMgr; + + ::osl::Mutex maMutex; + ::cppu::OMultiTypeInterfaceContainerHelper maListeners; + css::media::ZoomLevel meZoomLevel; + Player& mrPlayer; + HWND mnFrameWnd; + HWND mnParentWnd; + int mnPointerType; + + void ImplLayoutVideoWindow(); +}; + +} // namespace avmedia::win + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/avmedia/source/win/winuno.cxx b/avmedia/source/win/winuno.cxx new file mode 100644 index 000000000..90b1f3e40 --- /dev/null +++ b/avmedia/source/win/winuno.cxx @@ -0,0 +1,59 @@ +/* -*- 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 "wincommon.hxx" +#include "manager.hxx" +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +using namespace ::com::sun::star; + + +// - factory methods - + + +static uno::Reference< uno::XInterface > create_MediaPlayer( const uno::Reference< lang::XMultiServiceFactory >& rxFact ) +{ + return uno::Reference< uno::XInterface >( *new ::avmedia::win::Manager( rxFact ) ); +} + +extern "C" SAL_DLLPUBLIC_EXPORT void* avmediawin_component_getFactory( const char* pImplName, void* pServiceManager, void* ) +{ + uno::Reference< lang::XSingleServiceFactory > xFactory; + void* pRet = nullptr; + + if( rtl_str_compare( pImplName, "com.sun.star.comp.avmedia.Manager_DirectX" ) == 0 ) + { + const OUString aServiceName( "com.sun.star.media.Manager_DirectX" ); + + xFactory.set( ::cppu::createSingleFactory( + static_cast< lang::XMultiServiceFactory* >( pServiceManager ), + "com.sun.star.comp.avmedia.Manager_DirectX", + create_MediaPlayer, uno::Sequence< OUString >( &aServiceName, 1 ) ) ); + } + + if( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |