summaryrefslogtreecommitdiffstats
path: root/avmedia/source/win
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--avmedia/source/win/avmediawin.component25
-rw-r--r--avmedia/source/win/framegrabber.cxx225
-rw-r--r--avmedia/source/win/framegrabber.hxx57
-rw-r--r--avmedia/source/win/interface.hxx120
-rw-r--r--avmedia/source/win/manager.cxx77
-rw-r--r--avmedia/source/win/manager.hxx51
-rw-r--r--avmedia/source/win/player.cxx463
-rw-r--r--avmedia/source/win/player.hxx119
-rw-r--r--avmedia/source/win/wincommon.hxx44
-rw-r--r--avmedia/source/win/window.cxx495
-rw-r--r--avmedia/source/win/window.hxx114
-rw-r--r--avmedia/source/win/winuno.cxx59
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: */