diff options
author | Herbert Dürr <hdu@apache.org> | 2014-05-12 13:39:08 +0000 |
---|---|---|
committer | Tor Lillqvist <tml@collabora.com> | 2014-05-15 18:49:14 +0300 |
commit | f3b314413336eb60e66886f48b56149bb586d830 (patch) | |
tree | 57c9ccfc6de4f0281d85709dfacacd4d75a07df9 /avmedia | |
parent | bdb3f642973b7c7b9ce8bdae1344e4ab520f942a (diff) |
AOO: #i124875# support Mac AV-Foundation API for multimedia content
Adapted as needed and gbuildified by tml. For the files that actually
are Objective-C++ use the .mm suffix.
Change-Id: Ieec40b722df6463a1061d19d38154828ff8adca2
Diffstat (limited to 'avmedia')
-rw-r--r-- | avmedia/Library_avmediaMacAVF.mk | 47 | ||||
-rw-r--r-- | avmedia/Module_avmedia.mk | 3 | ||||
-rw-r--r-- | avmedia/source/inc/mediamisc.hxx | 1 | ||||
-rw-r--r-- | avmedia/source/macavf/avmediaMacAVF.component | 25 | ||||
-rw-r--r-- | avmedia/source/macavf/framegrabber.hxx | 63 | ||||
-rw-r--r-- | avmedia/source/macavf/framegrabber.mm | 136 | ||||
-rw-r--r-- | avmedia/source/macavf/macavfcommon.hxx | 87 | ||||
-rw-r--r-- | avmedia/source/macavf/macavfuno.mm | 54 | ||||
-rw-r--r-- | avmedia/source/macavf/manager.hxx | 58 | ||||
-rw-r--r-- | avmedia/source/macavf/manager.mm | 90 | ||||
-rw-r--r-- | avmedia/source/macavf/player.hxx | 95 | ||||
-rw-r--r-- | avmedia/source/macavf/player.mm | 474 | ||||
-rw-r--r-- | avmedia/source/macavf/window.hxx | 122 | ||||
-rw-r--r-- | avmedia/source/macavf/window.mm | 339 | ||||
-rw-r--r-- | avmedia/source/quicktime/framegrabber.hxx | 2 | ||||
-rw-r--r-- | avmedia/source/quicktime/framegrabber.mm | 9 | ||||
-rw-r--r-- | avmedia/source/quicktime/player.mm | 4 |
17 files changed, 1596 insertions, 13 deletions
diff --git a/avmedia/Library_avmediaMacAVF.mk b/avmedia/Library_avmediaMacAVF.mk new file mode 100644 index 000000000000..b123130c4d53 --- /dev/null +++ b/avmedia/Library_avmediaMacAVF.mk @@ -0,0 +1,47 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# 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/. +# + +$(eval $(call gb_Library_Library,avmediaMacAVF)) + +$(eval $(call gb_Library_set_componentfile,avmediaMacAVF,avmedia/source/macavf/avmediaMacAVF)) + +$(eval $(call gb_Library_set_include,avmediaMacAVF,\ + $$(INCLUDE) \ + -I$(SRCDIR)/avmedia/source/inc \ +)) + +$(eval $(call gb_Library_use_external,avmediaMacAVF,boost_headers)) + +$(eval $(call gb_Library_use_sdk_api,avmediaMacAVF)); + +$(eval $(call gb_Library_use_libraries,avmediaMacAVF,\ + comphelper \ + cppu \ + cppuhelper \ + sal \ + tl \ + vcl \ + $(gb_UWINAPI) \ +)) + +$(eval $(call gb_Library_use_system_darwin_frameworks,avmediaMacAVF,\ + AVFoundation \ + Cocoa \ + CoreMedia \ +)) + +$(eval $(call gb_Library_add_objcxxobjects,avmediaMacAVF,\ + avmedia/source/macavf/framegrabber \ + avmedia/source/macavf/macavfuno \ + avmedia/source/macavf/manager \ + avmedia/source/macavf/player \ + avmedia/source/macavf/window \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/avmedia/Module_avmedia.mk b/avmedia/Module_avmedia.mk index 5884cbec2899..6046ab5d4e2a 100644 --- a/avmedia/Module_avmedia.mk +++ b/avmedia/Module_avmedia.mk @@ -36,14 +36,13 @@ $(eval $(call gb_Module_add_targets,avmedia,\ endif ifeq ($(OS),MACOSX) -ifneq ($(CPUNAME),X86_64) ifneq ($(ENABLE_MACOSX_SANDBOX),TRUE) $(eval $(call gb_Module_add_targets,avmedia,\ + Library_avmediaMacAVF \ Library_avmediaQuickTime \ )) endif endif -endif ifneq ($(ENABLE_DIRECTX),) $(eval $(call gb_Module_add_targets,avmedia,\ diff --git a/avmedia/source/inc/mediamisc.hxx b/avmedia/source/inc/mediamisc.hxx index 6a86cfb93786..38a1e9db3f96 100644 --- a/avmedia/source/inc/mediamisc.hxx +++ b/avmedia/source/inc/mediamisc.hxx @@ -31,6 +31,7 @@ class ResMgr; #else #ifdef MACOSX #define AVMEDIA_MANAGER_SERVICE_NAME "com.sun.star.comp.avmedia.Manager_QuickTime" +#define AVMEDIA_MANAGER_SERVICE_NAME_FALLBACK1 "com.sun.star.comp.avmedia.Manager_MacAVF" #else #define AVMEDIA_MANAGER_SERVICE_NAME_OLD "com.sun.star.comp.avmedia.Manager_GStreamer_0_10" #define AVMEDIA_MANAGER_SERVICE_NAME "com.sun.star.comp.avmedia.Manager_GStreamer" diff --git a/avmedia/source/macavf/avmediaMacAVF.component b/avmedia/source/macavf/avmediaMacAVF.component new file mode 100644 index 000000000000..376576ff5d2d --- /dev/null +++ b/avmedia/source/macavf/avmediaMacAVF.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="avmediaMacAVF" xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.avmedia.Manager_MacAVF"> + <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 000000000000..14020cd82e4c --- /dev/null +++ b/avmedia/source/macavf/framegrabber.hxx @@ -0,0 +1,63 @@ +/* -*- 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_MACAVF_FRAMEGRABBER_HXX +#define INCLUDED_AVMEDIA_SOURCE_MACAVF_FRAMEGRABBER_HXX + +#include "macavfcommon.hxx" + +#include "com/sun/star/media/XFrameGrabber.hdl" + +namespace avmedia { namespace macavf { + +// ---------------- +// - FrameGrabber - +// ---------------- + +class FrameGrabber : public ::cppu::WeakImplHelper2 < ::com::sun::star::media::XFrameGrabber, + ::com::sun::star::lang::XServiceInfo > +{ +public: + + explicit FrameGrabber( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& ); + virtual ~FrameGrabber(); + + bool create( const ::rtl::OUString& rURL ); + + // XFrameGrabber + virtual ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > SAL_CALL grabFrame( double fMediaTime ) throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + +private: + + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMgr; + + AVAssetImageGenerator* mpImageGen; +}; + +} // namespace macavf +} // namespace avmedia + +#endif // INCLUDED_AVMEDIA_SOURCE_MACAVF_FRAMEGRABBER_HXX + +/* 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 000000000000..9f06ebdd8c19 --- /dev/null +++ b/avmedia/source/macavf/framegrabber.mm @@ -0,0 +1,136 @@ +/* -*- 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 <tools/stream.hxx> +#include <vcl/graph.hxx> +#include <vcl/cvtgrf.hxx> +#include <unotools/localfilehelper.hxx> + +using namespace ::com::sun::star; + +namespace avmedia { namespace macavf { + +// ---------------- +// - FrameGrabber - +// ---------------- + +FrameGrabber::FrameGrabber( const uno::Reference< lang::XMultiServiceFactory >& /*rxMgr*/ ) +: mpImageGen( NULL ) +{} + +// ------------------------------------------------------------------------------ + +FrameGrabber::~FrameGrabber() +{ + if( mpImageGen ) + CFRelease( mpImageGen ); +} + +// ------------------------------------------------------------------------------ + +bool FrameGrabber::create( const ::rtl::OUString& rURL ) +{ + // TODO: use AVPlayer's movie directly instead of loading it here? + + NSString* pNSStr = [NSString stringWithCharacters:rURL.getStr() length:rURL.getLength()]; + NSURL* pNSURL = [NSURL URLWithString: [pNSStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + AVAsset* pMovie = [AVURLAsset URLAssetWithURL:pNSURL options:nil]; + if( !pMovie ) + { + OSL_TRACE( "AVGrabber::create() cannot load url=\"%s\"", [pNSStr UTF8String] ); + return false; + } + if( [[pMovie tracksWithMediaType:AVMediaTypeVideo] count] == 0) + { + OSL_TRACE( "AVGrabber::create() found no video in url=\"%s\"", [pNSStr UTF8String] ); + return false; + } + + mpImageGen = [AVAssetImageGenerator assetImageGeneratorWithAsset:pMovie]; + CFRetain( mpImageGen ); + return true; +} + +// ------------------------------------------------------------------------------ + +uno::Reference< graphic::XGraphic > SAL_CALL FrameGrabber::grabFrame( double fMediaTime ) + throw (uno::RuntimeException) +{ + uno::Reference< graphic::XGraphic > xRet; + if( !mpImageGen ) + return xRet; + OSL_TRACE( "AVPlayer::grabFrame( %.3fsec)", fMediaTime ); + + // get the requested image from the movie + CGImage* pCGImage = [mpImageGen copyCGImageAtTime:CMTimeMakeWithSeconds(fMediaTime,1000) actualTime:NULL error:NULL]; + + // convert the image to a TIFF-formatted byte-array + CFMutableDataRef pCFData = CFDataCreateMutable( kCFAllocatorDefault, 0 ); + CGImageDestination* pCGImgDest = CGImageDestinationCreateWithData( pCFData, kUTTypeTIFF, 1, 0 ); + CGImageDestinationAddImage( pCGImgDest, pCGImage, NULL ); + CGImageDestinationFinalize( pCGImgDest ); + CFRelease( pCGImgDest ); + const long nBitmapLen = CFDataGetLength( pCFData ); + void* pBitmapBytes = (void*)CFDataGetBytePtr( pCFData ); + + // convert the image into the return-value type which is a graphic::XGraphic + SvMemoryStream aMemStm( pBitmapBytes, nBitmapLen, STREAM_READ | STREAM_WRITE ); + Graphic aGraphic; + if( GraphicConverter::Import( aMemStm, aGraphic, CVT_TIF ) == ERRCODE_NONE ) + xRet = aGraphic.GetXGraphic(); + + // clean up resources + CFRelease( pCFData ); + return xRet; +} + +// ------------------------------------------------------------------------------ + +::rtl::OUString SAL_CALL FrameGrabber::getImplementationName( ) + throw (uno::RuntimeException) +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_MACAVF_FRAMEGRABBER_IMPLEMENTATIONNAME ) ); +} + +// ------------------------------------------------------------------------------ + +sal_Bool SAL_CALL FrameGrabber::supportsService( const ::rtl::OUString& ServiceName ) + throw (uno::RuntimeException) +{ + return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( AVMEDIA_MACAVF_FRAMEGRABBER_SERVICENAME ) ); +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< ::rtl::OUString > SAL_CALL FrameGrabber::getSupportedServiceNames( ) + throw (uno::RuntimeException) +{ + uno::Sequence< ::rtl::OUString > aRet(1); + aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( AVMEDIA_MACAVF_FRAMEGRABBER_SERVICENAME ) ); + + return aRet; +} + +} // namespace macavf +} // namespace avmedia + +/* 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 000000000000..7082724ac27e --- /dev/null +++ b/avmedia/source/macavf/macavfcommon.hxx @@ -0,0 +1,87 @@ +/* -*- 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_MACAVF_MACAVFCOMMON_HXX +#define INCLUDED_AVMEDIA_SOURCE_MACAVF_MACAVFCOMMON_HXX + +#ifdef MACOSX +#include <premac.h> +#import <Cocoa/Cocoa.h> +#import <AVFoundation/AVFoundation.h> +#include <postmac.h> +#endif +#include <osl/mutex.hxx> +#include <rtl/ustring.hxx> +#include <tools/debug.hxx> +#include <tools/stream.hxx> +#include <tools/urlobj.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.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/XComponent.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_MANAGER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Manager_MacAVF" +#define AVMEDIA_MACAVF_MANAGER_SERVICENAME "com.sun.star.media.Manager_MacAVF" + +#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 + +@interface MacAVObserverObject : NSObject +- (void)observeValueForKeyPath:(NSString*)pKeyPath ofObject:(id)pObject change:(NSDictionary*)pChangeDict context:(void*)pContext; +- (void)onNotification:(NSNotification*)pNotification; +@end + +namespace avmedia { namespace macavf { + +class MacAVObserverHandler +{ +private: + static MacAVObserverObject* mpMacAVObserverObject; +public: + MacAVObserverObject* getObserver( void ) const; + virtual bool handleObservation( NSString* pKeyPath ) = 0; +}; + +}} + +#endif // MACAVF_COMMON_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/avmedia/source/macavf/macavfuno.mm b/avmedia/source/macavf/macavfuno.mm new file mode 100644 index 000000000000..0b95913fb816 --- /dev/null +++ b/avmedia/source/macavf/macavfuno.mm @@ -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 . + */ + +#include "macavfcommon.hxx" +#include "manager.hxx" + +using namespace ::com::sun::star; + +static uno::Reference< uno::XInterface > SAL_CALL create_MediaPlayer( const uno::Reference< lang::XMultiServiceFactory >& rxFact ) +{ + return uno::Reference< uno::XInterface >( *new ::avmedia::macavf::Manager( rxFact ) ); +} + +extern "C" SAL_DLLPUBLIC_EXPORT void* SAL_CALL avmediaMacAVF_component_getFactory( const sal_Char* pImplName, void* pServiceManager, void* /* pRegistryKey */ ) +{ + uno::Reference< lang::XSingleServiceFactory > xFactory; + void* pRet = 0; + + if( rtl_str_compare( pImplName, AVMEDIA_MACAVF_MANAGER_IMPLEMENTATIONNAME ) == 0 ) + { + const ::rtl::OUString aServiceName( ::rtl::OUString::createFromAscii( AVMEDIA_MACAVF_MANAGER_SERVICENAME ) ); + + xFactory = uno::Reference< lang::XSingleServiceFactory >( ::cppu::createSingleFactory( + reinterpret_cast< lang::XMultiServiceFactory* >( pServiceManager ), + ::rtl::OUString::createFromAscii( AVMEDIA_MACAVF_MANAGER_IMPLEMENTATIONNAME ), + create_MediaPlayer, uno::Sequence< ::rtl::OUString >( &aServiceName, 1 ) ) ); + } + + if( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + +/* 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 000000000000..7385dd1ba1f1 --- /dev/null +++ b/avmedia/source/macavf/manager.hxx @@ -0,0 +1,58 @@ +/* -*- 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_MACAVF_MANAGER_HXX +#define INCLUDED_AVMEDIA_SOURCE_MACAVF_MANAGER_HXX + +#include "macavfcommon.hxx" + +#include "com/sun/star/media/XManager.hdl" + +// ----------- +// - Manager - +// ----------- + +namespace avmedia { namespace macavf { + +class Manager : public ::cppu::WeakImplHelper2 < ::com::sun::star::media::XManager, + ::com::sun::star::lang::XServiceInfo > +{ +public: + + Manager( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxMgr ); + ~Manager(); + + // XManager + virtual ::com::sun::star::uno::Reference< ::com::sun::star::media::XPlayer > SAL_CALL createPlayer( const ::rtl::OUString& aURL ) throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); +private: + + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMgr; +}; + +} // namespace macavf +} // namespace avmedia + +#endif // INCLUDED_AVMEDIA_SOURCE_MACAVF_MANAGER_HXX + +/* 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 000000000000..8fc0f2bf75d4 --- /dev/null +++ b/avmedia/source/macavf/manager.mm @@ -0,0 +1,90 @@ +/* -*- 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> + +using namespace ::com::sun::star; + +namespace avmedia { namespace macavf { + +// ---------------- +// - Manager - +// ---------------- + +Manager::Manager( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) : + mxMgr( rxMgr ) +{ + OSL_TRACE( "Constructing avmedia::macavf::Manager" ); +} + +// ------------------------------------------------------------------------------ + +Manager::~Manager() +{} + +// ------------------------------------------------------------------------------ + +uno::Reference< media::XPlayer > SAL_CALL Manager::createPlayer( const ::rtl::OUString& rURL ) + throw (uno::RuntimeException) +{ + Player* pPlayer( new Player( mxMgr ) ); + uno::Reference< media::XPlayer > xRet( pPlayer ); + INetURLObject aURL( rURL ); + + OSL_TRACE( "avmediamacavf: Manager::createPlayer" ); + + if( !pPlayer->create( aURL.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS ) ) ) + xRet = uno::Reference< media::XPlayer >(); + + return xRet; +} + +// ------------------------------------------------------------------------------ + +::rtl::OUString SAL_CALL Manager::getImplementationName( ) + throw (uno::RuntimeException) +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_MACAVF_MANAGER_IMPLEMENTATIONNAME ) ); +} + +// ------------------------------------------------------------------------------ + +sal_Bool SAL_CALL Manager::supportsService( const ::rtl::OUString& ServiceName ) + throw (uno::RuntimeException) +{ + return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( AVMEDIA_MACAVF_MANAGER_SERVICENAME ) ); +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< ::rtl::OUString > SAL_CALL Manager::getSupportedServiceNames( ) + throw (uno::RuntimeException) +{ + uno::Sequence< ::rtl::OUString > aRet(1); + aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( AVMEDIA_MACAVF_MANAGER_SERVICENAME ) ); + + return aRet; +} + +} // namespace macavf +} // namespace avmedia + +/* 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 000000000000..2cdf8a1fd2b0 --- /dev/null +++ b/avmedia/source/macavf/player.hxx @@ -0,0 +1,95 @@ +/* -*- 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_MACAVF_PLAYER_HXX +#define INCLUDED_AVMEDIA_SOURCE_MACAVF_PLAYER_HXX + +#include <osl/conditn.h> +#include "macavfcommon.hxx" + +#include "com/sun/star/media/XPlayer.hdl" + +namespace avmedia { namespace macavf { + +/* +// ---------- +// - Player - +// ---------- +*/ + +class Player +: public MacAVObserverHandler +, public ::cppu::WeakImplHelper2< ::com::sun::star::media::XPlayer, + ::com::sun::star::lang::XServiceInfo > +{ +public: + explicit Player( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& ); + virtual ~Player(); + + bool create( const ::rtl::OUString& rURL ); + + // XPlayer + virtual void SAL_CALL start() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL stop() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isPlaying() throw (::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getDuration() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setMediaTime( double fTime ) throw (::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getMediaTime() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setStopTime( double fTime ) throw (::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getStopTime() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setRate( double fRate ) throw (::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getRate() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setPlaybackLoop( sal_Bool bSet ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isPlaybackLoop() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setMute( sal_Bool bSet ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isMute() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setVolumeDB( sal_Int16 nVolumeDB ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getVolumeDB() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Size SAL_CALL getPreferredPlayerWindowSize( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::media::XPlayerWindow > SAL_CALL createPlayerWindow( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::media::XFrameGrabber > SAL_CALL createFrameGrabber( ) throw (::com::sun::star::uno::RuntimeException); + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + + AVAsset* getMovie(); + AVPlayer* getAVPlayer() const { return mpPlayer; } + virtual bool handleObservation( NSString* pKeyPath ); + +private: + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMgr; + + ::rtl::OUString maURL; + + AVPlayer* mpPlayer; + + float mfUnmutedVolume; + double mfStopTime; + + bool mbMuted; + bool mbLooping; +}; + +} // namespace macavf +} // namespace avmedia + +#endif // INCLUDED_AVMEDIA_SOURCE_MACAVF_PLAYER_HXX + +/* 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 000000000000..38478da14be2 --- /dev/null +++ b/avmedia/source/macavf/player.mm @@ -0,0 +1,474 @@ +/* -*- 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 <cmath> // for log10() + +using namespace ::com::sun::star; + +#include <unordered_map> +typedef std::unordered_map<NSObject*,avmedia::macavf::MacAVObserverHandler*> HandlersForObject; + +@implementation MacAVObserverObject +{ + HandlersForObject maHandlersForObject; +} +- (void)observeValueForKeyPath:(NSString*)pKeyPath ofObject:(id)pObject change:(NSDictionary*)pChangeDict context:(void*)pContext +{ + (void) pObject; + NSString* pDictStr = [NSString stringWithFormat:@"%@", pChangeDict]; + OSL_TRACE( "MacAVObserver::onKeyChange k=\"%s\" c=%s", [pKeyPath UTF8String], [pDictStr UTF8String]); + avmedia::macavf::MacAVObserverHandler* pHandler = (avmedia::macavf::MacAVObserverHandler*)pContext; + pHandler->handleObservation( pKeyPath ); +} + +- (void)onNotification:(NSNotification*)pNotification +{ + NSString* pNoteName = (NSString*)[pNotification name]; + OSL_TRACE( "MacAVObserver::onNotification key=\"%s\"", [pNoteName UTF8String]); + 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 { namespace macavf { + +MacAVObserverObject* MacAVObserverHandler::mpMacAVObserverObject = NULL; + +MacAVObserverObject* MacAVObserverHandler::getObserver() const +{ + if( !mpMacAVObserverObject) + { + mpMacAVObserverObject = [MacAVObserverObject alloc]; + [mpMacAVObserverObject retain]; + } + return mpMacAVObserverObject; +} + + +// ---------------- +// - Player - +// ---------------- + +Player::Player( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) +: mxMgr( rxMgr ) +, mpPlayer( NULL ) +, 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 ); +} + +// ------------------------------------------------------------------------------ + +AVAsset* Player::getMovie() +{ + if( !mpPlayer ) + return nil; + AVAsset* pMovie = [[mpPlayer currentItem] asset]; + OSL_ASSERT( pMovie ); + return pMovie; +} + +// ------------------------------------------------------------------------------ + +bool Player::handleObservation( NSString* pKeyPath ) +{ + OSL_TRACE( "AVPlayer::handleObservation key=\"%s\"", [pKeyPath UTF8String]); + if( [pKeyPath isEqualToString:AVPlayerItemDidPlayToEndTimeNotification]) + { + OSL_TRACE( "AVPlayer replay=%d", mbLooping); + if( mbLooping ) + setMediaTime( 0.0); + } + return true; +} + +// ------------------------------------------------------------------------------ + +bool Player::create( const ::rtl::OUString& rURL ) +{ + maURL = rURL; + + // get the media asset + NSString* aNSStr = [NSString stringWithCharacters:rURL.getStr() length:rURL.getLength()]; + NSURL* aNSURL = [NSURL URLWithString: [aNSStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + // 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() + throw (uno::RuntimeException) +{ + if( !mpPlayer ) + return; +#if 0 + const AVPlayerStatus eStatus = [mpPlayer status]; + OSL_TRACE ("Player::start status=%d", (int)eStatus); + if( eStatus == AVPlayerStatusReadyToPlay) +#endif + [mpPlayer play]; + // else // TODO: delay until it becomes ready +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Player::stop() + throw (uno::RuntimeException) +{ + if( !mpPlayer ) + return; + const bool bPlaying = isPlaying(); + OSL_TRACE ("Player::stop() playing=%d", bPlaying); + if( bPlaying ) + [mpPlayer pause]; +} + +// ------------------------------------------------------------------------------ + +sal_Bool SAL_CALL Player::isPlaying() + throw (uno::RuntimeException) +{ + if( !mpPlayer ) + return false; + const float fRate = [mpPlayer rate]; + return (fRate != 0.0); +} + +// ------------------------------------------------------------------------------ + +double SAL_CALL Player::getDuration() + throw (uno::RuntimeException) +{ + // slideshow checks for non-zero duration, so cheat here + double duration = 0.01; + + if( mpPlayer ) + { + AVPlayerItem* pItem = [mpPlayer currentItem]; + duration = CMTimeGetSeconds( [pItem duration] ); + } + + return duration; +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Player::setMediaTime( double fTime ) + throw (uno::RuntimeException) +{ + OSL_TRACE ("Player::setMediaTime( %.3fsec)", fTime); + if( mpPlayer ) + [mpPlayer seekToTime: CMTimeMakeWithSeconds(fTime,1000) ]; +} + +// ------------------------------------------------------------------------------ + +double SAL_CALL Player::getMediaTime() + throw (uno::RuntimeException) +{ + if( !mpPlayer ) + return 0.0; + + const double position = CMTimeGetSeconds( [mpPlayer currentTime] ); + OSL_TRACE( "Player::getMediaTime() = %.3fsec", position); + if( position >= mfStopTime ) + if( isPlaying() ) + stop(); + + return position; +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Player::setStopTime( double fTime ) + throw (uno::RuntimeException) +{ + OSL_TRACE ("Player::setStopTime( %.3fsec)", fTime); + mfStopTime = fTime; +} + +// ------------------------------------------------------------------------------ + +double SAL_CALL Player::getStopTime() + throw (uno::RuntimeException) +{ + return mfStopTime; +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Player::setRate( double fRate ) + throw (uno::RuntimeException) +{ + OSL_TRACE ("Player::setRate( %.3f)", fRate); + if( !mpPlayer ) + return; + + // playback rate: 0 = stop, 1 = normal speed, 2 = double speed, -1 = normal speed backwards + [mpPlayer setRate: fRate]; +} + +// ------------------------------------------------------------------------------ + +double SAL_CALL Player::getRate() + throw (uno::RuntimeException) +{ + // macavf: 0 = stop, 1 = normal speed, 2 = double speed, -1 = normal speed backwards + const double fRate = mpPlayer ? (double)[mpPlayer rate] : 1.0; + OSL_TRACE ("Player::getRate() = %.3f", fRate); + return fRate; +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet ) + throw (uno::RuntimeException) +{ + OSL_TRACE ("Player::setPlaybackLoop( %d)", bSet ); + mbLooping = bSet; +} + +// ------------------------------------------------------------------------------ + +sal_Bool SAL_CALL Player::isPlaybackLoop() + throw (uno::RuntimeException) +{ + const bool bRet = mbLooping; + OSL_TRACE ("Player::isPlaybackLoop() = %d", bRet ); + return bRet; +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Player::setMute( sal_Bool bSet ) + throw (uno::RuntimeException) +{ + OSL_TRACE( "Player::setMute(%d), was-muted: %d unmuted-volume: %.3f", bSet, mbMuted, mfUnmutedVolume ); + + if( !mpPlayer ) + return; + + mbMuted = (bSet == TRUE); + [mpPlayer setMuted:mbMuted]; +} + +// ------------------------------------------------------------------------------ + +sal_Bool SAL_CALL Player::isMute() + throw (uno::RuntimeException) +{ + OSL_TRACE ("Player::isMuted() = %d", mbMuted); + return mbMuted; +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB ) + throw (uno::RuntimeException) +{ + // -40dB <-> AVPlayer volume 0.0 + // 0dB <-> AVPlayer volume 1.0 + mfUnmutedVolume = (nVolumeDB <= -40) ? 0.0 : pow( 10.0, nVolumeDB / 20.0 ); + OSL_TRACE( "Player::setVolume(%ddB), muted=%d, unmuted-volume: %.3f", nVolumeDB, mbMuted, mfUnmutedVolume ); + + // change volume + if( !mbMuted && mpPlayer ) + [mpPlayer setVolume:mfUnmutedVolume]; +} + +// ------------------------------------------------------------------------------ + +sal_Int16 SAL_CALL Player::getVolumeDB() + throw (uno::RuntimeException) +{ + if( !mpPlayer ) + return 0; + + // get the actual volume + const float fVolume = [mpPlayer volume]; + + // convert into Dezibel value + // -40dB <-> AVPlayer volume 0.0 + // 0dB <-> AVPlayer volume 1.0 + const int nVolumeDB = (fVolume <= 0) ? -40 : lrint( 20.0*log10(fVolume)); + + return (sal_Int16)nVolumeDB; +} + +// ------------------------------------------------------------------------------ + +awt::Size SAL_CALL Player::getPreferredPlayerWindowSize() + throw (uno::RuntimeException) +{ + awt::Size aSize( 0, 0 ); // default size + + AVAsset* pMovie = [[mpPlayer currentItem] asset]; + NSArray* pVideoTracks = [pMovie tracksWithMediaType:AVMediaTypeVideo]; + if ([pVideoTracks count] > 0) + { + AVAssetTrack* pFirstVideoTrack =(AVAssetTrack*)pVideoTracks[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 ) + throw (uno::RuntimeException) +{ + // get the preferred window size + const awt::Size aSize( getPreferredPlayerWindowSize() ); + OSL_TRACE( "Player::createPlayerWindow %dx%d argsLength: %d", aSize.Width, aSize.Height, aArguments.getLength() ); + + // get the parent view + sal_IntPtr nNSViewPtr = NULL; + aArguments[0] >>= nNSViewPtr; + NSView* pParentView = reinterpret_cast<NSView*>(nNSViewPtr); + + // check the window parameters + uno::Reference< ::media::XPlayerWindow > xRet; + if( (aSize.Width <= 0) || (aSize.Height <= 0) || (pParentView == NULL) ) + return xRet; + + // create the window + ::avmedia::macavf::Window* pWindow = new ::avmedia::macavf::Window( mxMgr, *this, pParentView ); + xRet = pWindow; + return xRet; +} + +// ------------------------------------------------------------------------------ + +uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber() + throw (uno::RuntimeException) +{ + uno::Reference< media::XFrameGrabber > xRet; + OSL_TRACE ("Player::createFrameGrabber"); + + if( !maURL.isEmpty() ) + { + FrameGrabber* pGrabber = new FrameGrabber( mxMgr ); + if( pGrabber->create( maURL ) ) + xRet = pGrabber; + } + + return xRet; +} + +// ------------------------------------------------------------------------------ + +::rtl::OUString SAL_CALL Player::getImplementationName( ) + throw (uno::RuntimeException) +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_MACAVF_PLAYER_IMPLEMENTATIONNAME ) ); +} + +// ------------------------------------------------------------------------------ + +sal_Bool SAL_CALL Player::supportsService( const ::rtl::OUString& ServiceName ) + throw (uno::RuntimeException) +{ + return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( AVMEDIA_MACAVF_PLAYER_SERVICENAME ) ); +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< ::rtl::OUString > SAL_CALL Player::getSupportedServiceNames( ) + throw (uno::RuntimeException) +{ + uno::Sequence< ::rtl::OUString > aRet(1); + aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( AVMEDIA_MACAVF_PLAYER_SERVICENAME ) ); + + return aRet; +} + +} // namespace macavf +} // namespace avmedia + +/* 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 000000000000..68022a591c35 --- /dev/null +++ b/avmedia/source/macavf/window.hxx @@ -0,0 +1,122 @@ +/* -*- 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_MACAVF_WINDOW_HXX +#define INCLUDED_AVMEDIA_SOURCE_MACAVF_WINDOW_HXX + +#include "macavfcommon.hxx" +#include <cppuhelper/interfacecontainer.h> + +#include "com/sun/star/media/XPlayerWindow.hdl" + +// --------------- +// - MyMediaView - +// --------------- + +@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 { namespace macavf { + +// --------------- +// - Window - +// --------------- + +class Player; + +class Window +: public MacAVObserverHandler +, public ::cppu::WeakImplHelper2 < ::com::sun::star::media::XPlayerWindow, + ::com::sun::star::lang::XServiceInfo > +{ +public: + + Window( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& i_rxMgr, + Player& i_rPlayer, + NSView* i_pParentView + ); + virtual ~Window(); + + bool create( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ); + void processGraphEvent(); + void updatePointer(); + + // XPlayerWindow + virtual void SAL_CALL update( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL setZoomLevel( ::com::sun::star::media::ZoomLevel ZoomLevel ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::media::ZoomLevel SAL_CALL getZoomLevel( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setPointerType( sal_Int32 nPointerType ) throw (::com::sun::star::uno::RuntimeException); + + // XWindow + virtual void SAL_CALL setPosSize( sal_Int32 X, sal_Int32 Y, sal_Int32 Width, sal_Int32 Height, sal_Int16 Flags ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Rectangle SAL_CALL getPosSize( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setVisible( sal_Bool Visible ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setEnable( sal_Bool Enable ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setFocus( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addWindowListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeWindowListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addFocusListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XFocusListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeFocusListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XFocusListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addKeyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XKeyListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeKeyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XKeyListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addMouseListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XMouseListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeMouseListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XMouseListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addMouseMotionListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XMouseMotionListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeMouseMotionListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XMouseMotionListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addPaintListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XPaintListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removePaintListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XPaintListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + + // XComponent + virtual void SAL_CALL dispose( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + + virtual bool handleObservation( NSString* pKeyPath ); + +private: + + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMgr; + + ::osl::Mutex maMutex; + ::cppu::OMultiTypeInterfaceContainerHelper maListeners; + ::com::sun::star::media::ZoomLevel meZoomLevel; + Player& mrPlayer; + int mnPointerType; + + NSView* mpView; // parent-view == movie-view + AVPlayerLayer* mpPlayerLayer; + + void ImplLayoutVideoWindow(); +}; + +} // namespace macavf +} // namespace avmedia + +#endif // INCLUDED_AVMEDIA_SOURCE_MACAVF_WINDOW_HXX + +/* 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 000000000000..af54f0cad40a --- /dev/null +++ b/avmedia/source/macavf/window.mm @@ -0,0 +1,339 @@ +/* -*- 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 { namespace macavf { + +// --------------- +// - Window - +// --------------- + +Window::Window( const uno::Reference< lang::XMultiServiceFactory >& i_rxMgr, Player& i_rPlayer, NSView* i_pParentView ) +: mxMgr( i_rxMgr ) +, maListeners( maMutex ) +, meZoomLevel( media::ZoomLevel_NOT_AVAILABLE ) +, mrPlayer( i_rPlayer ) +, mnPointerType( awt::SystemPointer::ARROW ) +, mpView( i_pParentView ) +, mpPlayerLayer( NULL ) +{ + OSL_TRACE ("Constructing an avmedia::macavf::Window"); + 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; + const int nAudioCount = [pMovie tracksWithMediaType:AVMediaTypeAudio].count; + OSL_TRACE( "Found %d video and %d audio tracks.", nVideoCount, nAudioCount ); + (void)nAudioCount; + if( nVideoCount <= 0 ) + return; + + // setup the AVPlayerLayer + [pAVPlayer retain]; + [pAVPlayer pause]; + mpPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:pAVPlayer]; + [mpPlayerLayer retain]; + [mpPlayerLayer setFrame:[mpView frame]]; + [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::create( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& /* aArguments */ ) +{ + return true; +} + +// ------------------------------------------------------------------------------ + +bool Window::handleObservation( NSString* pKeyPath ) +{ + OSL_TRACE( "AVPlayer::handleObservation key=\"%s\"", [pKeyPath UTF8String]); + const BOOL bReadyForDisplay = [mpPlayerLayer isReadyForDisplay]; + [mpPlayerLayer setHidden:!bReadyForDisplay]; + return true; +} + +// XPlayerWindow +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::update() + throw (uno::RuntimeException) +{} + +// ------------------------------------------------------------------------------ + +sal_Bool SAL_CALL Window::setZoomLevel( media::ZoomLevel /* eZoomLevel */ ) + throw (uno::RuntimeException) +{ + return false; +} + +// ------------------------------------------------------------------------------ + +media::ZoomLevel SAL_CALL Window::getZoomLevel( ) + throw (uno::RuntimeException) +{ + return meZoomLevel; +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::setPointerType( sal_Int32 nPointerType ) + throw (uno::RuntimeException) +{ + mnPointerType = nPointerType; +} + +// XWindow +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::setPosSize( sal_Int32 X, sal_Int32 Y, sal_Int32 Width, sal_Int32 Height, sal_Int16 /* Flags */ ) + throw (uno::RuntimeException) +{ + OSL_TRACE( "AVWindow::setPosSize( %dx%d%+d%+d)", (int)Width,(int)Height,(int)X,(int)Y);//###### + 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]; + [mpPlayerLayer setFrame: [mpView frame]]; +} + +// ------------------------------------------------------------------------------ + +awt::Rectangle SAL_CALL Window::getPosSize() + throw (uno::RuntimeException) +{ + 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 ) + throw (uno::RuntimeException) +{ + OSL_TRACE ("Window::setVisible(%d)", bVisible); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::setEnable( sal_Bool bEnable ) + throw (uno::RuntimeException) +{ + OSL_TRACE ("Window::setEnable(%d)", bEnable); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::setFocus() + throw (uno::RuntimeException) +{ + OSL_TRACE ("Window::setFocus"); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::addWindowListener( const uno::Reference< awt::XWindowListener >& xListener ) + throw (uno::RuntimeException) +{ + maListeners.addInterface( getCppuType( &xListener ), xListener ); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::removeWindowListener( const uno::Reference< awt::XWindowListener >& xListener ) + throw (uno::RuntimeException) +{ + maListeners.removeInterface( getCppuType( &xListener ), xListener ); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::addFocusListener( const uno::Reference< awt::XFocusListener >& xListener ) + throw (uno::RuntimeException) +{ + maListeners.addInterface( getCppuType( &xListener ), xListener ); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::removeFocusListener( const uno::Reference< awt::XFocusListener >& xListener ) + throw (uno::RuntimeException) +{ + maListeners.removeInterface( getCppuType( &xListener ), xListener ); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::addKeyListener( const uno::Reference< awt::XKeyListener >& xListener ) + throw (uno::RuntimeException) +{ + maListeners.addInterface( getCppuType( &xListener ), xListener ); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::removeKeyListener( const uno::Reference< awt::XKeyListener >& xListener ) + throw (uno::RuntimeException) +{ + maListeners.removeInterface( getCppuType( &xListener ), xListener ); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::addMouseListener( const uno::Reference< awt::XMouseListener >& xListener ) + throw (uno::RuntimeException) +{ + maListeners.addInterface( getCppuType( &xListener ), xListener ); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::removeMouseListener( const uno::Reference< awt::XMouseListener >& xListener ) + throw (uno::RuntimeException) +{ + maListeners.removeInterface( getCppuType( &xListener ), xListener ); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::addMouseMotionListener( const uno::Reference< awt::XMouseMotionListener >& xListener ) + throw (uno::RuntimeException) +{ + maListeners.addInterface( getCppuType( &xListener ), xListener ); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::removeMouseMotionListener( const uno::Reference< awt::XMouseMotionListener >& xListener ) + throw (uno::RuntimeException) +{ + maListeners.removeInterface( getCppuType( &xListener ), xListener ); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::addPaintListener( const uno::Reference< awt::XPaintListener >& xListener ) + throw (uno::RuntimeException) +{ + maListeners.addInterface( getCppuType( &xListener ), xListener ); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::removePaintListener( const uno::Reference< awt::XPaintListener >& xListener ) + throw (uno::RuntimeException) +{ + maListeners.removeInterface( getCppuType( &xListener ), xListener ); +} + + +// XComponent +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::dispose( ) + throw (uno::RuntimeException) +{ +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) + throw (uno::RuntimeException) +{ + maListeners.addInterface( getCppuType( &xListener ), xListener ); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Window::removeEventListener( const uno::Reference< lang::XEventListener >& xListener ) + throw (uno::RuntimeException) +{ + maListeners.removeInterface( getCppuType( &xListener ), xListener ); +} + +// XServiceInfo +// ------------------------------------------------------------------------------ + +::rtl::OUString SAL_CALL Window::getImplementationName( ) + throw (uno::RuntimeException) +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_MACAVF_WINDOW_IMPLEMENTATIONNAME ) ); +} + +// ------------------------------------------------------------------------------ + +sal_Bool SAL_CALL Window::supportsService( const ::rtl::OUString& ServiceName ) + throw (uno::RuntimeException) +{ + return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( AVMEDIA_MACAVF_WINDOW_SERVICENAME ) ); +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< ::rtl::OUString > SAL_CALL Window::getSupportedServiceNames( ) + throw (uno::RuntimeException) +{ + uno::Sequence< ::rtl::OUString > aRet(1); + aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( AVMEDIA_MACAVF_WINDOW_SERVICENAME ) ); + + return aRet; +} + +} // namespace macavf +} // namespace avmedia + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/avmedia/source/quicktime/framegrabber.hxx b/avmedia/source/quicktime/framegrabber.hxx index cb7021532328..31112e92cbde 100644 --- a/avmedia/source/quicktime/framegrabber.hxx +++ b/avmedia/source/quicktime/framegrabber.hxx @@ -49,12 +49,10 @@ public: virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); private: - ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMgr; OUString maURL; QTMovie* mpMovie; bool mbInitialized; - long mnVersion; }; } // namespace quicktime diff --git a/avmedia/source/quicktime/framegrabber.mm b/avmedia/source/quicktime/framegrabber.mm index 9e563fb280a7..4e3e177c1426 100644 --- a/avmedia/source/quicktime/framegrabber.mm +++ b/avmedia/source/quicktime/framegrabber.mm @@ -39,13 +39,10 @@ namespace avmedia { namespace quicktime { FrameGrabber::FrameGrabber( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) : mxMgr( rxMgr ) { - OSErr result; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - // we have version 7.01 or later, initialize - mpMovie = [QTMovie movie]; - [mpMovie retain]; - mbInitialized = true; + mpMovie = [QTMovie movie]; + [mpMovie retain]; + mbInitialized = true; [pool release]; } diff --git a/avmedia/source/quicktime/player.mm b/avmedia/source/quicktime/player.mm index c668fd770e90..a6b48869734c 100644 --- a/avmedia/source/quicktime/player.mm +++ b/avmedia/source/quicktime/player.mm @@ -43,11 +43,9 @@ Player::Player( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) : mbInitialized( false ), maSizeCondition( osl_createCondition() ) { - OSErr result; - NSApplicationLoad(); NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - mbInitialized = true; + mbInitialized = true; [pool release]; } |