summaryrefslogtreecommitdiffstats
path: root/avmedia/source/macavf
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /avmedia/source/macavf
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'avmedia/source/macavf')
-rw-r--r--avmedia/source/macavf/avmediaMacAVF.component26
-rw-r--r--avmedia/source/macavf/framegrabber.hxx54
-rw-r--r--avmedia/source/macavf/framegrabber.mm108
-rw-r--r--avmedia/source/macavf/macavfcommon.hxx86
-rw-r--r--avmedia/source/macavf/manager.hxx49
-rw-r--r--avmedia/source/macavf/manager.mm77
-rw-r--r--avmedia/source/macavf/player.hxx83
-rw-r--r--avmedia/source/macavf/player.mm359
-rw-r--r--avmedia/source/macavf/window.hxx108
-rw-r--r--avmedia/source/macavf/window.mm260
10 files changed, 1210 insertions, 0 deletions
diff --git a/avmedia/source/macavf/avmediaMacAVF.component b/avmedia/source/macavf/avmediaMacAVF.component
new file mode 100644
index 000000000..3cb9966c1
--- /dev/null
+++ b/avmedia/source/macavf/avmediaMacAVF.component
@@ -0,0 +1,26 @@
+<?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@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.avmedia.Manager_MacAVF"
+ constructor="com_sun_star_comp_avmedia_Manager_MacAVF_get_implementation">
+ <service name="com.sun.star.media.Manager_MacAVF"/>
+ </implementation>
+</component>
diff --git a/avmedia/source/macavf/framegrabber.hxx b/avmedia/source/macavf/framegrabber.hxx
new file mode 100644
index 000000000..5e0c749d9
--- /dev/null
+++ b/avmedia/source/macavf/framegrabber.hxx
@@ -0,0 +1,54 @@
+/* -*- 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 "macavfcommon.hxx"
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/media/XFrameGrabber.hpp>
+
+namespace avmedia::macavf {
+
+class FrameGrabber : public ::cppu::WeakImplHelper< css::media::XFrameGrabber,
+ css::lang::XServiceInfo >
+{
+public:
+
+ explicit FrameGrabber();
+ virtual ~FrameGrabber() override;
+
+ bool create( AVAsset* pMovie );
+
+ // 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:
+
+ AVAssetImageGenerator* mpImageGen;
+};
+
+} // namespace avmedia::macavf
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/avmedia/source/macavf/framegrabber.mm b/avmedia/source/macavf/framegrabber.mm
new file mode 100644
index 000000000..e0b8bad61
--- /dev/null
+++ b/avmedia/source/macavf/framegrabber.mm
@@ -0,0 +1,108 @@
+/* -*- 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 "framegrabber.hxx"
+#include "player.hxx"
+
+#include <sal/log.hxx>
+#include <tools/stream.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/cvtgrf.hxx>
+#include <unotools/localfilehelper.hxx>
+
+using namespace ::com::sun::star;
+
+namespace avmedia::macavf {
+
+FrameGrabber::FrameGrabber()
+: mpImageGen( nullptr )
+{}
+
+
+FrameGrabber::~FrameGrabber()
+{
+ if( mpImageGen )
+ CFRelease( mpImageGen );
+}
+
+
+bool FrameGrabber::create( AVAsset* pMovie )
+{
+ if( [[pMovie tracksWithMediaType:AVMediaTypeVideo] count] == 0)
+ {
+ SAL_WARN("avmedia", "AVGrabber::create() found no video content!" );
+ return false;
+ }
+
+ mpImageGen = [AVAssetImageGenerator assetImageGeneratorWithAsset:pMovie];
+ CFRetain( mpImageGen );
+ return true;
+}
+
+
+uno::Reference< graphic::XGraphic > SAL_CALL FrameGrabber::grabFrame( double fMediaTime )
+{
+ uno::Reference< graphic::XGraphic > xRet;
+ if( !mpImageGen )
+ return xRet;
+
+ // get the requested image from the movie
+ CGImage* pCGImage = [mpImageGen copyCGImageAtTime:CMTimeMakeWithSeconds(fMediaTime,1000) actualTime:nullptr error:nullptr];
+
+ // convert the image to a TIFF-formatted byte-array
+ CFMutableDataRef pCFData = CFDataCreateMutable( kCFAllocatorDefault, 0 );
+ SAL_WNODEPRECATED_DECLARATIONS_PUSH // kUTTypeTIFF (12.0)
+ CGImageDestination* pCGImgDest = CGImageDestinationCreateWithData( pCFData, kUTTypeTIFF, 1, nullptr );
+ SAL_WNODEPRECATED_DECLARATIONS_POP
+ CGImageDestinationAddImage( pCGImgDest, pCGImage, nullptr );
+ CGImageDestinationFinalize( pCGImgDest );
+ CFRelease( pCGImgDest );
+ const CFIndex nBitmapLen = CFDataGetLength( pCFData );
+ UInt8 * pBitmapBytes = const_cast<UInt8 *>(CFDataGetBytePtr( pCFData ));
+
+ // convert the image into the return-value type which is a graphic::XGraphic
+ SvMemoryStream aMemStm( pBitmapBytes, nBitmapLen, StreamMode::READ | StreamMode::WRITE );
+ Graphic aGraphic;
+ if( GraphicConverter::Import( aMemStm, aGraphic, ConvertDataFormat::TIF ) == ERRCODE_NONE )
+ xRet = aGraphic.GetXGraphic();
+
+ // clean up resources
+ CFRelease( pCFData );
+ return xRet;
+}
+
+
+OUString SAL_CALL FrameGrabber::getImplementationName( )
+{
+ return AVMEDIA_MACAVF_FRAMEGRABBER_IMPLEMENTATIONNAME;
+}
+
+sal_Bool SAL_CALL FrameGrabber::supportsService( const OUString& ServiceName )
+{
+ return ServiceName == AVMEDIA_MACAVF_FRAMEGRABBER_SERVICENAME;
+}
+
+uno::Sequence< OUString > SAL_CALL FrameGrabber::getSupportedServiceNames( )
+{
+ return { AVMEDIA_MACAVF_FRAMEGRABBER_SERVICENAME };
+}
+
+} // namespace avmedia::macavf
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/avmedia/source/macavf/macavfcommon.hxx b/avmedia/source/macavf/macavfcommon.hxx
new file mode 100644
index 000000000..b031f1ecc
--- /dev/null
+++ b/avmedia/source/macavf/macavfcommon.hxx
@@ -0,0 +1,86 @@
+/* -*- 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 <premac.h>
+#import <Cocoa/Cocoa.h>
+#import <AVFoundation/AVFoundation.h>
+#include <postmac.h>
+
+#include <unordered_map>
+
+#include <osl/mutex.hxx>
+#include <rtl/ustring.hxx>
+#include <tools/stream.hxx>
+#include <tools/urlobj.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 AVMEDIA_MACAVF_PLAYER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Player_MacAVF"
+#define AVMEDIA_MACAVF_PLAYER_SERVICENAME "com.sun.star.media.Player_MacAVF"
+
+#define AVMEDIA_MACAVF_WINDOW_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Window_MacAVF"
+#define AVMEDIA_MACAVF_WINDOW_SERVICENAME "com.sun.star.media.Window_MacAVF"
+
+#define AVMEDIA_MACAVF_FRAMEGRABBER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.FrameGrabber_MacAVF"
+#define AVMEDIA_MACAVF_FRAMEGRABBER_SERVICENAME "com.sun.star.media.FrameGrabber_MacAVF"
+
+
+// MacAVObserver handles the notifications used in the AVFoundation framework
+
+namespace avmedia::macavf { class MacAVObserverHandler; }
+
+typedef std::unordered_map<NSObject*,avmedia::macavf::MacAVObserverHandler*> HandlersForObject;
+
+@interface MacAVObserverObject : NSObject
+{
+ HandlersForObject maHandlersForObject;
+}
+- (void)observeValueForKeyPath:(NSString*)pKeyPath ofObject:(id)pObject change:(NSDictionary*)pChangeDict context:(void*)pContext;
+- (void)onNotification:(NSNotification*)pNotification;
+@end
+
+namespace avmedia::macavf {
+
+class MacAVObserverHandler
+{
+private:
+ static MacAVObserverObject* mpMacAVObserverObject;
+public:
+ virtual ~MacAVObserverHandler() {}
+ static MacAVObserverObject* getObserver();
+ virtual bool handleObservation( NSString* pKeyPath ) = 0;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/avmedia/source/macavf/manager.hxx b/avmedia/source/macavf/manager.hxx
new file mode 100644
index 000000000..9072b3800
--- /dev/null
+++ b/avmedia/source/macavf/manager.hxx
@@ -0,0 +1,49 @@
+/* -*- 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 "macavfcommon.hxx"
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/media/XManager.hpp>
+
+
+namespace avmedia::macavf {
+
+class Manager : public ::cppu::WeakImplHelper< css::media::XManager,
+ css::lang::XServiceInfo >
+{
+public:
+
+ Manager();
+ virtual ~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;
+};
+
+} // namespace avmedia::macavf
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/avmedia/source/macavf/manager.mm b/avmedia/source/macavf/manager.mm
new file mode 100644
index 000000000..d240bb27a
--- /dev/null
+++ b/avmedia/source/macavf/manager.mm
@@ -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 <tools/urlobj.hxx>
+#include <osl/diagnose.h>
+#include <rtl/ref.hxx>
+
+using namespace ::com::sun::star;
+
+namespace avmedia::macavf {
+
+Manager::Manager()
+{
+}
+
+
+Manager::~Manager()
+{}
+
+
+uno::Reference< media::XPlayer > SAL_CALL Manager::createPlayer( const OUString& rURL )
+{
+ rtl::Reference<Player> xPlayer( new Player() );
+ INetURLObject aURL( rURL );
+
+ if( !xPlayer->create( aURL.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous ) ) )
+ return {};
+
+ return uno::Reference<media::XPlayer>(xPlayer);
+}
+
+
+OUString SAL_CALL Manager::getImplementationName( )
+{
+ return "com.sun.star.comp.avmedia.Manager_MacAVF";
+}
+
+
+sal_Bool SAL_CALL Manager::supportsService( const OUString& ServiceName )
+{
+ return ServiceName == "com.sun.star.media.Manager_MacAVF";
+}
+
+
+uno::Sequence< OUString > SAL_CALL Manager::getSupportedServiceNames( )
+{
+ return { "com.sun.star.media.Manager_MacAVF" };
+}
+
+} // namespace avmedia::macavf
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_avmedia_Manager_MacAVF_get_implementation(
+ css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new ::avmedia::macavf::Manager());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/avmedia/source/macavf/player.hxx b/avmedia/source/macavf/player.hxx
new file mode 100644
index 000000000..3dc41b347
--- /dev/null
+++ b/avmedia/source/macavf/player.hxx
@@ -0,0 +1,83 @@
+/* -*- 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 <osl/conditn.h>
+#include "macavfcommon.hxx"
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/media/XPlayer.hpp>
+
+namespace avmedia::macavf {
+
+class Player
+: public MacAVObserverHandler
+, public ::cppu::WeakImplHelper< css::media::XPlayer,
+ css::lang::XServiceInfo >
+{
+public:
+ explicit Player();
+ virtual ~Player() override;
+
+ bool create( const OUString& rURL );
+ bool create( AVAsset* );
+
+ // 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;
+ /// @throws css::uno::RuntimeException
+ virtual void setStopTime( double fTime );
+ /// @throws css::uno::RuntimeException
+ virtual double getStopTime();
+ 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;
+
+ AVPlayer* getAVPlayer() const { return mpPlayer; }
+ virtual bool handleObservation( NSString* pKeyPath ) override;
+
+private:
+
+ AVPlayer* mpPlayer;
+
+ float mfUnmutedVolume;
+ double mfStopTime;
+
+ bool mbMuted;
+ bool mbLooping;
+};
+
+} // namespace avmedia::macavf
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/avmedia/source/macavf/player.mm b/avmedia/source/macavf/player.mm
new file mode 100644
index 000000000..401cba74c
--- /dev/null
+++ b/avmedia/source/macavf/player.mm
@@ -0,0 +1,359 @@
+/* -*- 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 "player.hxx"
+#include "framegrabber.hxx"
+#include "window.hxx"
+#include <rtl/ref.hxx>
+
+#include <cmath> // for log10()
+
+using namespace ::com::sun::star;
+
+@implementation MacAVObserverObject
+
+- (void)observeValueForKeyPath:(NSString*)pKeyPath ofObject:(id)pObject change:(NSDictionary*)pChangeDict context:(void*)pContext
+{
+ (void) pObject;
+ (void) pChangeDict;
+ avmedia::macavf::MacAVObserverHandler* pHandler = static_cast<avmedia::macavf::MacAVObserverHandler*>(pContext);
+ pHandler->handleObservation( pKeyPath );
+}
+
+- (void)onNotification:(NSNotification*)pNotification
+{
+ NSString* pNoteName = [pNotification name];
+ HandlersForObject::iterator it = maHandlersForObject.find( [pNotification object]);
+ if( it != maHandlersForObject.end() )
+ (*it).second->handleObservation( pNoteName );
+}
+
+- (void)setHandlerForObject:(NSObject*)pObject handler:(avmedia::macavf::MacAVObserverHandler*)pHandler
+{
+ maHandlersForObject[ pObject] = pHandler;
+}
+
+- (void)removeHandlerForObject:(NSObject*)pObject
+{
+ maHandlersForObject.erase( pObject);
+}
+
+@end
+
+
+namespace avmedia::macavf {
+
+MacAVObserverObject* MacAVObserverHandler::mpMacAVObserverObject = nullptr;
+
+MacAVObserverObject* MacAVObserverHandler::getObserver()
+{
+ if( !mpMacAVObserverObject)
+ {
+ mpMacAVObserverObject = [MacAVObserverObject alloc];
+ [mpMacAVObserverObject retain];
+ }
+ return mpMacAVObserverObject;
+}
+
+
+Player::Player()
+: mpPlayer( nullptr )
+, mfUnmutedVolume( 0 )
+, mfStopTime( DBL_MAX )
+, mbMuted( false )
+, mbLooping( false )
+{}
+
+
+Player::~Player()
+{
+ if( !mpPlayer )
+ return;
+ // remove the observers
+ [mpPlayer removeObserver:getObserver() forKeyPath:@"currentItem.status"];
+ AVPlayerItem* pOldPlayerItem = [mpPlayer currentItem];
+ [[NSNotificationCenter defaultCenter] removeObserver:getObserver()
+ name:AVPlayerItemDidPlayToEndTimeNotification
+ object:pOldPlayerItem];
+ [getObserver() removeHandlerForObject:pOldPlayerItem];
+ // release the AVPlayer
+ CFRelease( mpPlayer );
+}
+
+
+bool Player::handleObservation( NSString* pKeyPath )
+{
+ if( [pKeyPath isEqualToString:AVPlayerItemDidPlayToEndTimeNotification])
+ {
+ if( mbLooping )
+ setMediaTime( 0.0);
+ }
+ return true;
+}
+
+
+bool Player::create( const OUString& rURL )
+{
+ // get the media asset
+ NSString* aNSStr = [NSString stringWithCharacters:reinterpret_cast<unichar const *>(rURL.getStr()) length:rURL.getLength()];
+ SAL_WNODEPRECATED_DECLARATIONS_PUSH
+ //TODO: 10.11 stringByAddingPercentEscapesUsingEncoding
+ NSURL* aNSURL = [NSURL URLWithString: [aNSStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
+ SAL_WNODEPRECATED_DECLARATIONS_POP
+ // get the matching AVPlayerItem
+ AVPlayerItem* pPlayerItem = [AVPlayerItem playerItemWithURL:aNSURL];
+
+ // create or update the AVPlayer with the new AVPlayerItem
+ if( !mpPlayer )
+ {
+ mpPlayer = [AVPlayer playerWithPlayerItem:pPlayerItem];
+ CFRetain( mpPlayer );
+ [mpPlayer setActionAtItemEnd:AVPlayerActionAtItemEndNone];
+ }
+ else
+ {
+ // remove the obsoleted observers
+ AVPlayerItem* pOldPlayerItem = [mpPlayer currentItem];
+ [mpPlayer removeObserver:getObserver() forKeyPath:@"currentItem.status"];
+ [getObserver() removeHandlerForObject:pOldPlayerItem];
+ [[NSNotificationCenter defaultCenter] removeObserver:getObserver()
+ name:AVPlayerItemDidPlayToEndTimeNotification
+ object:pOldPlayerItem];
+ // replace the playeritem
+ [mpPlayer replaceCurrentItemWithPlayerItem:pPlayerItem];
+ }
+
+ // observe the status of the current player item
+ [mpPlayer addObserver:getObserver() forKeyPath:@"currentItem.status" options:0 context:this];
+
+ // observe playback-end needed for playback looping
+ [[NSNotificationCenter defaultCenter] addObserver:getObserver()
+ selector:@selector(onNotification:)
+ name:AVPlayerItemDidPlayToEndTimeNotification
+ object:pPlayerItem];
+ [getObserver() setHandlerForObject:pPlayerItem handler:this];
+
+ return true;
+}
+
+
+void SAL_CALL Player::start()
+{
+ if( !mpPlayer )
+ return;
+
+ [mpPlayer play];
+ // else // TODO: delay until it becomes ready
+}
+
+
+void SAL_CALL Player::stop()
+{
+ if( !mpPlayer )
+ return;
+ const bool bPlaying = isPlaying();
+ if( bPlaying )
+ [mpPlayer pause];
+}
+
+
+sal_Bool SAL_CALL Player::isPlaying()
+{
+ if( !mpPlayer )
+ return false;
+ const float fRate = [mpPlayer rate];
+ return (fRate != 0.0);
+}
+
+
+double SAL_CALL Player::getDuration()
+{
+ // slideshow checks for non-zero duration, so cheat here
+ double duration = 0.01;
+
+ if( mpPlayer )
+ {
+ AVPlayerItem* pItem = [mpPlayer currentItem];
+ if( [pItem status] == AVPlayerItemStatusReadyToPlay )
+ duration = CMTimeGetSeconds( [pItem duration] );
+ else // fall back to AVAsset's best guess
+ duration = CMTimeGetSeconds( [[pItem asset] duration] );
+ }
+
+ return duration;
+}
+
+
+void SAL_CALL Player::setMediaTime( double fTime )
+{
+ if( mpPlayer )
+ [mpPlayer seekToTime: CMTimeMakeWithSeconds(fTime,1000) ];
+}
+
+
+double SAL_CALL Player::getMediaTime()
+{
+ if( !mpPlayer )
+ return 0.0;
+
+ const double position = CMTimeGetSeconds( [mpPlayer currentTime] );
+ if( position >= mfStopTime )
+ if( isPlaying() )
+ stop();
+
+ return position;
+}
+
+
+void Player::setStopTime( double fTime )
+{
+ mfStopTime = fTime;
+}
+
+
+double Player::getStopTime()
+{
+ return mfStopTime;
+}
+
+
+void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet )
+{
+ mbLooping = bSet;
+}
+
+
+sal_Bool SAL_CALL Player::isPlaybackLoop()
+{
+ return mbLooping;
+}
+
+
+void SAL_CALL Player::setMute( sal_Bool bSet )
+{
+ if( !mpPlayer )
+ return;
+
+ mbMuted = bSet;
+ [mpPlayer setMuted:mbMuted];
+}
+
+
+sal_Bool SAL_CALL Player::isMute()
+{
+ return mbMuted;
+}
+
+
+void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB )
+{
+ // -40dB <-> AVPlayer volume 0.0
+ // 0dB <-> AVPlayer volume 1.0
+ mfUnmutedVolume = (nVolumeDB <= -40) ? 0.0 : pow( 10.0, nVolumeDB / 20.0 );
+
+ // change volume
+ if( !mbMuted && mpPlayer )
+ [mpPlayer setVolume:mfUnmutedVolume];
+}
+
+
+sal_Int16 SAL_CALL Player::getVolumeDB()
+{
+ if( !mpPlayer )
+ return 0;
+
+ // get the actual volume
+ const float fVolume = [mpPlayer volume];
+
+ // convert into Decibel value
+ // -40dB <-> AVPlayer volume 0.0
+ // 0dB <-> AVPlayer volume 1.0
+ const int nVolumeDB = (fVolume <= 0) ? -40 : lrint( 20.0*log10(fVolume));
+
+ return static_cast<sal_Int16>(nVolumeDB);
+}
+
+
+awt::Size SAL_CALL Player::getPreferredPlayerWindowSize()
+{
+ awt::Size aSize( 0, 0 ); // default size
+
+ AVAsset* pMovie = [[mpPlayer currentItem] asset];
+ NSArray* pVideoTracks = [pMovie tracksWithMediaType:AVMediaTypeVideo];
+ if ([pVideoTracks count] > 0)
+ {
+ AVAssetTrack* pFirstVideoTrack = static_cast<AVAssetTrack*>([pVideoTracks objectAtIndex:0]);
+ const CGSize aPrefSize = [pFirstVideoTrack naturalSize];
+ aSize = awt::Size( aPrefSize.width, aPrefSize.height );
+ }
+
+ return aSize;
+}
+
+
+uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( const uno::Sequence< uno::Any >& aArguments )
+{
+ // get the preferred window size
+ const awt::Size aSize( getPreferredPlayerWindowSize() );
+
+ // get the parent view
+ sal_IntPtr nNSViewPtr = 0;
+ aArguments[0] >>= nNSViewPtr;
+ NSView* pParentView = reinterpret_cast<NSView*>(nNSViewPtr);
+
+ // check the window parameters
+ if( (aSize.Width <= 0) || (aSize.Height <= 0) || (pParentView == nullptr) )
+ return {};
+
+ // create the window
+ return new ::avmedia::macavf::Window( *this, pParentView );
+}
+
+
+uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber()
+{
+ rtl::Reference<FrameGrabber> pGrabber = new FrameGrabber();
+ AVAsset* pMovie = [[mpPlayer currentItem] asset];
+ if( !pGrabber->create( pMovie ) )
+ return {};
+
+ return pGrabber;
+}
+
+
+OUString SAL_CALL Player::getImplementationName( )
+{
+ return AVMEDIA_MACAVF_PLAYER_IMPLEMENTATIONNAME;
+}
+
+
+sal_Bool SAL_CALL Player::supportsService( const OUString& ServiceName )
+{
+ return ServiceName == AVMEDIA_MACAVF_PLAYER_SERVICENAME;
+}
+
+
+uno::Sequence< OUString > SAL_CALL Player::getSupportedServiceNames( )
+{
+ return { AVMEDIA_MACAVF_PLAYER_SERVICENAME };
+}
+
+} // namespace avmedia::macavf
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/avmedia/source/macavf/window.hxx b/avmedia/source/macavf/window.hxx
new file mode 100644
index 000000000..14fdaf389
--- /dev/null
+++ b/avmedia/source/macavf/window.hxx
@@ -0,0 +1,108 @@
+/* -*- 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 "macavfcommon.hxx"
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/multicontainer2.hxx>
+
+#include <com/sun/star/media/XPlayerWindow.hpp>
+
+
+@interface MyMediaView : NSView
+@property (nonatomic, readonly, strong) AVPlayer* player;
+@property (nonatomic, readonly, strong) AVPlayerLayer* playerLayer;
+@property (nonatomic, retain) NSURL* videoURL;
+- (void) play;
+@end
+
+namespace avmedia::macavf {
+
+class Player;
+
+class Window
+: public MacAVObserverHandler
+, public ::cppu::WeakImplHelper< css::media::XPlayerWindow,
+ css::lang::XServiceInfo >
+{
+public:
+
+ Window( Player& i_rPlayer,
+ NSView* i_pParentView
+ );
+ virtual ~Window() override;
+
+ 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;
+
+ virtual bool handleObservation( NSString* pKeyPath ) override;
+
+private:
+
+ ::osl::Mutex maMutex;
+ comphelper::OMultiTypeInterfaceContainerHelper2 maListeners;
+ css::media::ZoomLevel meZoomLevel;
+ Player& mrPlayer;
+ int mnPointerType;
+
+ NSView* mpView; // parent-view == movie-view
+ AVPlayerLayer* mpPlayerLayer;
+
+ void ImplLayoutVideoWindow();
+};
+
+} // namespace avmedia::macavf
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/avmedia/source/macavf/window.mm b/avmedia/source/macavf/window.mm
new file mode 100644
index 000000000..fdb2e5065
--- /dev/null
+++ b/avmedia/source/macavf/window.mm
@@ -0,0 +1,260 @@
+/* -*- 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 <com/sun/star/awt/SystemPointer.hpp>
+#include <com/sun/star/awt/PosSize.hpp>
+
+#include "window.hxx"
+#include "player.hxx"
+
+using namespace ::com::sun::star;
+
+
+namespace avmedia::macavf {
+
+Window::Window( Player& i_rPlayer, NSView* i_pParentView )
+: maListeners( maMutex )
+, meZoomLevel( media::ZoomLevel_NOT_AVAILABLE )
+, mrPlayer( i_rPlayer )
+, mnPointerType( awt::SystemPointer::ARROW )
+, mpView( i_pParentView )
+, mpPlayerLayer( nullptr )
+{
+ if( !mpView ) // sanity check
+ return;
+
+ // check the media asset for video content
+ AVPlayer* pAVPlayer = mrPlayer.getAVPlayer();
+ AVAsset* pMovie = [[pAVPlayer currentItem] asset];
+ const int nVideoCount = [pMovie tracksWithMediaType:AVMediaTypeVideo].count;
+ if( nVideoCount <= 0 )
+ return;
+
+ // setup the AVPlayerLayer
+ [pAVPlayer retain];
+ [pAVPlayer pause];
+ mpPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:pAVPlayer];
+ [mpPlayerLayer retain];
+ NSRect viewFrame = [mpView frame];
+ [mpPlayerLayer setFrame:CGRectMake(viewFrame.origin.x, viewFrame.origin.y, viewFrame.size.width, viewFrame.size.height)];
+ [mpPlayerLayer setHidden:YES];
+ [mpPlayerLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
+ [mpPlayerLayer addObserver:getObserver() forKeyPath:@"readyForDisplay" options:0 context:this];
+
+ // setup the target view
+ [mpView setWantsLayer:YES];
+ [mpView.layer addSublayer:mpPlayerLayer];
+}
+
+
+Window::~Window()
+{
+ [mpPlayerLayer removeObserver:getObserver() forKeyPath:@"readyForDisplay"];
+ [mpPlayerLayer release];
+}
+
+
+bool Window::handleObservation( NSString* /*pKeyPath*/ )
+{
+ const bool bReadyForDisplay = [mpPlayerLayer isReadyForDisplay];
+ [mpPlayerLayer setHidden:!bReadyForDisplay];
+ return true;
+}
+
+// XPlayerWindow
+
+void SAL_CALL Window::update()
+{}
+
+
+sal_Bool SAL_CALL Window::setZoomLevel( media::ZoomLevel /* eZoomLevel */ )
+{
+ return false;
+}
+
+
+media::ZoomLevel SAL_CALL Window::getZoomLevel( )
+{
+ return meZoomLevel;
+}
+
+
+void SAL_CALL Window::setPointerType( sal_Int32 nPointerType )
+{
+ mnPointerType = nPointerType;
+}
+
+// XWindow
+
+void SAL_CALL Window::setPosSize( sal_Int32 /*X*/, sal_Int32 /*Y*/, sal_Int32 Width, sal_Int32 Height, sal_Int16 /* Flags */ )
+{
+ if( !mpView )
+ return;
+ NSRect aRect = [mpView frame];
+ // NOTE: if( (Flags & awt::PosSize::WIDTH) )
+ aRect.size.width = Width;
+ // NOTE: if( (Flags & awt::PosSize::HEIGHT) )
+ aRect.size.height = Height;
+
+ [mpView setFrameSize: aRect.size];
+ NSRect viewFrame = [mpView frame];
+ [mpPlayerLayer setFrame:CGRectMake(viewFrame.origin.x, viewFrame.origin.y, viewFrame.size.width, viewFrame.size.height)];
+}
+
+
+awt::Rectangle SAL_CALL Window::getPosSize()
+{
+ awt::Rectangle aRet;
+
+ NSRect aRect = [mpView frame];
+ aRet.X = aRet.Y = 0;
+ aRet.Width = aRect.size.width;
+ aRet.Height = aRect.size.height;
+
+ return aRet;
+}
+
+
+void SAL_CALL Window::setVisible( sal_Bool /*bVisible*/ )
+{
+}
+
+
+void SAL_CALL Window::setEnable( sal_Bool /*bEnable*/ )
+{
+}
+
+
+void SAL_CALL Window::setFocus()
+{
+}
+
+
+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 );
+}
+
+
+// XComponent
+
+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 );
+}
+
+// XServiceInfo
+
+OUString SAL_CALL Window::getImplementationName( )
+{
+ return AVMEDIA_MACAVF_WINDOW_IMPLEMENTATIONNAME;
+}
+
+
+sal_Bool SAL_CALL Window::supportsService( const OUString& ServiceName )
+{
+ return ServiceName == AVMEDIA_MACAVF_WINDOW_SERVICENAME;
+}
+
+
+uno::Sequence< OUString > SAL_CALL Window::getSupportedServiceNames( )
+{
+ return { AVMEDIA_MACAVF_WINDOW_SERVICENAME };
+}
+
+} // namespace avmedia::macavf
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */