Bump version to 6.0-36
[LibreOffice.git] / slideshow / source / engine / shapes / viewmediashape.cxx
blob4f3255591a882e4aa1b1a4055fab9180bb5ceaf0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include <tools/diagnose_ex.h>
24 #include <math.h>
26 #include <comphelper/anytostring.hxx>
27 #include <cppuhelper/exc_hlp.hxx>
29 #include <vcl/canvastools.hxx>
30 #include <vcl/syschild.hxx>
31 #include <vcl/sysdata.hxx>
32 #include <vcl/window.hxx>
33 #include <vcl/graph.hxx>
35 #include <basegfx/utils/canvastools.hxx>
36 #include <basegfx/matrix/b2dhommatrixtools.hxx>
37 #include <basegfx/numeric/ftools.hxx>
38 #include <basegfx/polygon/b2dpolygon.hxx>
39 #include <basegfx/point/b2dpoint.hxx>
40 #include <basegfx/matrix/b2dhommatrix.hxx>
41 #include <basegfx/polygon/b2dpolygontools.hxx>
42 #include <basegfx/range/b2irange.hxx>
43 #include <canvas/canvastools.hxx>
44 #include <cppcanvas/vclfactory.hxx>
45 #include <cppcanvas/basegfxfactory.hxx>
46 #include <avmedia/mediawindow.hxx>
48 #if HAVE_FEATURE_OPENGL
49 #include <vcl/opengl/OpenGLContext.hxx>
50 #endif
52 #include <com/sun/star/awt/XWindow.hpp>
53 #include <com/sun/star/beans/XPropertySet.hpp>
54 #include <com/sun/star/lang/XComponent.hpp>
55 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
56 #include <com/sun/star/lang/NoSupportException.hpp>
57 #include <com/sun/star/media/XManager.hpp>
58 #include <com/sun/star/media/XPlayer.hpp>
59 #include <com/sun/star/media/XPlayerWindow.hpp>
60 #include <com/sun/star/presentation/XSlideShowView.hpp>
61 #include <com/sun/star/rendering/XCanvas.hpp>
63 #include "viewmediashape.hxx"
64 #include "mediashape.hxx"
65 #include <tools.hxx>
66 #include <unoview.hxx>
68 using namespace ::com::sun::star;
70 namespace slideshow
72 namespace internal
74 ViewMediaShape::ViewMediaShape( const ViewLayerSharedPtr& rViewLayer,
75 const uno::Reference< drawing::XShape >& rxShape,
76 const uno::Reference< uno::XComponentContext >& rxContext ) :
77 mpViewLayer( rViewLayer ),
78 mpEventHandlerParent(nullptr),
79 maWindowOffset( 0, 0 ),
80 maBounds(),
81 mxShape( rxShape ),
82 mxPlayer(),
83 mxPlayerWindow(),
84 mxComponentContext( rxContext ),
85 mbIsSoundEnabled(true)
87 ENSURE_OR_THROW( mxShape.is(), "ViewMediaShape::ViewMediaShape(): Invalid Shape" );
88 ENSURE_OR_THROW( mpViewLayer, "ViewMediaShape::ViewMediaShape(): Invalid View" );
89 ENSURE_OR_THROW( mpViewLayer->getCanvas(), "ViewMediaShape::ViewMediaShape(): Invalid ViewLayer canvas" );
90 ENSURE_OR_THROW( mxComponentContext.is(), "ViewMediaShape::ViewMediaShape(): Invalid component context" );
92 UnoViewSharedPtr xUnoView(std::dynamic_pointer_cast<UnoView>(rViewLayer));
93 if (xUnoView)
95 mbIsSoundEnabled = xUnoView->isSoundEnabled();
99 ViewMediaShape::~ViewMediaShape()
103 endMedia();
105 catch (const uno::Exception &e)
107 SAL_WARN("slideshow", e);
111 const ViewLayerSharedPtr& ViewMediaShape::getViewLayer() const
113 return mpViewLayer;
116 void ViewMediaShape::startMedia()
118 if( !mxPlayer.is() )
119 implInitialize( maBounds );
121 if (mxPlayer.is())
122 mxPlayer->start();
125 void ViewMediaShape::endMedia()
127 // shutdown player window
128 if( mxPlayerWindow.is() )
130 uno::Reference< lang::XComponent > xComponent( mxPlayerWindow, uno::UNO_QUERY );
132 if( xComponent.is() )
133 xComponent->dispose();
135 mxPlayerWindow.clear();
138 mpMediaWindow.disposeAndClear();
139 mpEventHandlerParent.disposeAndClear();
141 // shutdown player
142 if( mxPlayer.is() )
144 mxPlayer->stop();
146 uno::Reference< lang::XComponent > xComponent( mxPlayer, uno::UNO_QUERY );
148 if( xComponent.is() )
149 xComponent->dispose();
151 mxPlayer.clear();
155 void ViewMediaShape::pauseMedia()
157 if (mxPlayer.is())
158 mxPlayer->stop();
161 void ViewMediaShape::setMediaTime(double fTime)
163 if (mxPlayer.is())
164 mxPlayer->setMediaTime(fTime);
167 bool ViewMediaShape::render( const ::basegfx::B2DRectangle& rBounds ) const
169 #if !HAVE_FEATURE_AVMEDIA
170 (void) rBounds;
171 #else
172 ::cppcanvas::CanvasSharedPtr pCanvas = mpViewLayer->getCanvas();
174 if( !pCanvas )
175 return false;
177 if( !mpMediaWindow.get() && !mxPlayerWindow.is() )
179 uno::Reference< graphic::XGraphic > xGraphic;
180 uno::Reference< beans::XPropertySet > xPropSet( mxShape, uno::UNO_QUERY );
181 if (xPropSet.is())
183 xPropSet->getPropertyValue("FallbackGraphic") >>= xGraphic;
186 Graphic aGraphic(xGraphic);
187 const BitmapEx aBmp = aGraphic.GetBitmapEx();
189 uno::Reference< rendering::XBitmap > xBitmap(vcl::unotools::xBitmapFromBitmapEx(aBmp));
191 rendering::ViewState aViewState;
192 aViewState.AffineTransform = pCanvas->getViewState().AffineTransform;
194 rendering::RenderState aRenderState;
195 ::canvas::tools::initRenderState( aRenderState );
197 const ::Size aBmpSize( aBmp.GetSizePixel() );
199 const ::basegfx::B2DVector aScale( rBounds.getWidth() / aBmpSize.Width(),
200 rBounds.getHeight() / aBmpSize.Height() );
201 const basegfx::B2DHomMatrix aTranslation(basegfx::utils::createScaleTranslateB2DHomMatrix(
202 aScale, rBounds.getMinimum()));
203 ::canvas::tools::setRenderStateTransform( aRenderState, aTranslation );
205 pCanvas->getUNOCanvas()->drawBitmap( xBitmap,
206 aViewState,
207 aRenderState );
209 #endif
210 return true;
213 bool ViewMediaShape::resize( const ::basegfx::B2DRectangle& rNewBounds ) const
215 maBounds = rNewBounds;
217 ::cppcanvas::CanvasSharedPtr pCanvas = mpViewLayer->getCanvas();
219 if( !pCanvas )
220 return false;
222 if( !mxPlayerWindow.is() )
223 return true;
225 uno::Reference< beans::XPropertySet > xPropSet( pCanvas->getUNOCanvas()->getDevice(),
226 uno::UNO_QUERY );
228 uno::Reference< awt::XWindow > xParentWindow;
229 if( xPropSet.is() &&
230 getPropertyValue( xParentWindow,
231 xPropSet,
232 "Window") )
234 const awt::Rectangle aRect( xParentWindow->getPosSize() );
236 maWindowOffset.X = aRect.X;
237 maWindowOffset.Y = aRect.Y;
240 ::basegfx::B2DRange aTmpRange;
241 ::canvas::tools::calcTransformedRectBounds( aTmpRange,
242 rNewBounds,
243 mpViewLayer->getTransformation() );
244 const ::basegfx::B2IRange& rRangePix(
245 ::basegfx::unotools::b2ISurroundingRangeFromB2DRange( aTmpRange ));
247 mxPlayerWindow->setEnable( !rRangePix.isEmpty() );
249 if( rRangePix.isEmpty() )
250 return true;
252 const Point aPosPixel( rRangePix.getMinX() + maWindowOffset.X,
253 rRangePix.getMinY() + maWindowOffset.Y );
254 const Size aSizePixel( rRangePix.getMaxX() - rRangePix.getMinX(),
255 rRangePix.getMaxY() - rRangePix.getMinY() );
257 if( mpMediaWindow.get() )
259 if( mpEventHandlerParent )
261 mpEventHandlerParent->SetPosSizePixel( aPosPixel, aSizePixel );
262 mpMediaWindow->SetPosSizePixel( Point(0,0), aSizePixel );
264 else
266 mpMediaWindow->SetPosSizePixel( aPosPixel, aSizePixel );
268 mxPlayerWindow->setPosSize( 0, 0,
269 aSizePixel.Width(), aSizePixel.Height(),
270 0 );
272 else
274 mxPlayerWindow->setPosSize( aPosPixel.X(), aPosPixel.Y(),
275 aSizePixel.Width(), aSizePixel.Height(),
276 0 );
279 return true;
283 bool ViewMediaShape::implInitialize( const ::basegfx::B2DRectangle& rBounds )
285 if( !mxPlayer.is() && mxShape.is() )
287 ENSURE_OR_RETURN_FALSE( mpViewLayer->getCanvas(),
288 "ViewMediaShape::implInitialize(): Invalid layer canvas" );
290 uno::Reference< rendering::XCanvas > xCanvas( mpViewLayer->getCanvas()->getUNOCanvas() );
292 if( xCanvas.is() )
294 uno::Reference< beans::XPropertySet > xPropSet;
297 xPropSet.set( mxShape, uno::UNO_QUERY );
298 OUString sMimeType;
300 // create Player
301 if (xPropSet.is())
303 OUString aURL;
304 xPropSet->getPropertyValue("MediaMimeType") >>= sMimeType;
305 if ((xPropSet->getPropertyValue("PrivateTempFileURL") >>= aURL)
306 && !aURL.isEmpty())
308 implInitializeMediaPlayer( aURL, sMimeType );
310 else if (xPropSet->getPropertyValue("MediaURL") >>= aURL)
312 implInitializeMediaPlayer( aURL, sMimeType );
316 // create visible object
317 uno::Sequence< uno::Any > aDeviceParams;
319 if( ::canvas::tools::getDeviceInfo( xCanvas, aDeviceParams ).getLength() > 1 )
321 implInitializePlayerWindow( rBounds, aDeviceParams, sMimeType );
324 // set player properties
325 implSetMediaProperties( xPropSet );
327 catch( uno::RuntimeException& )
329 throw;
331 catch( uno::Exception& )
333 SAL_WARN( "slideshow", comphelper::anyToString( cppu::getCaughtException() ) );
338 return mxPlayer.is() || mxPlayerWindow.is();
342 void ViewMediaShape::implSetMediaProperties( const uno::Reference< beans::XPropertySet >& rxProps )
344 if( mxPlayer.is() )
346 mxPlayer->setMediaTime( 0.0 );
348 if( rxProps.is() )
350 bool bLoop( false );
351 getPropertyValue( bLoop,
352 rxProps,
353 "Loop");
354 mxPlayer->setPlaybackLoop( bLoop );
356 bool bMute( false );
357 getPropertyValue( bMute,
358 rxProps,
359 "Mute");
360 mxPlayer->setMute( bMute || !mbIsSoundEnabled);
362 sal_Int16 nVolumeDB(0);
363 getPropertyValue( nVolumeDB,
364 rxProps,
365 "VolumeDB");
366 mxPlayer->setVolumeDB( nVolumeDB );
368 if( mxPlayerWindow.is() )
370 media::ZoomLevel eZoom(media::ZoomLevel_FIT_TO_WINDOW);
371 getPropertyValue( eZoom,
372 rxProps,
373 "Zoom");
374 mxPlayerWindow->setZoomLevel( eZoom );
381 void ViewMediaShape::implInitializeMediaPlayer( const OUString& rMediaURL, const OUString& rMimeType )
383 #if !HAVE_FEATURE_AVMEDIA
384 (void) rMediaURL;
385 (void) rMimeType;
386 #else
387 if( !mxPlayer.is() )
391 if( !rMediaURL.isEmpty() )
393 mxPlayer.set( avmedia::MediaWindow::createPlayer( rMediaURL, ""/*TODO!*/, &rMimeType ),
394 uno::UNO_QUERY );
397 catch( uno::RuntimeException& )
399 throw;
401 catch( const uno::Exception& )
403 throw lang::NoSupportException( "No video support for " + rMediaURL );
406 #endif
410 void ViewMediaShape::implInitializePlayerWindow( const ::basegfx::B2DRectangle& rBounds,
411 const uno::Sequence< uno::Any >& rVCLDeviceParams,
412 const OUString& )
414 SAL_INFO("slideshow", "ViewMediaShape::implInitializePlayerWindow" );
415 if( !mpMediaWindow.get() && !rBounds.isEmpty() )
419 sal_Int64 aVal=0;
421 rVCLDeviceParams[ 1 ] >>= aVal;
423 vcl::Window* pWindow = reinterpret_cast< vcl::Window* >( aVal );
425 if( pWindow )
427 ::basegfx::B2DRange aTmpRange;
428 ::canvas::tools::calcTransformedRectBounds( aTmpRange,
429 rBounds,
430 mpViewLayer->getTransformation() );
431 const ::basegfx::B2IRange& rRangePix(
432 ::basegfx::unotools::b2ISurroundingRangeFromB2DRange( aTmpRange ));
434 if( !rRangePix.isEmpty() )
436 uno::Sequence< uno::Any > aArgs( 3 );
437 awt::Rectangle aAWTRect( rRangePix.getMinX(),
438 rRangePix.getMinY(),
439 rRangePix.getMaxX() - rRangePix.getMinX(),
440 rRangePix.getMaxY() - rRangePix.getMinY() );
442 mpMediaWindow.disposeAndClear();
443 mpMediaWindow = VclPtr<SystemChildWindow>::Create( pWindow, WB_CLIPCHILDREN );
444 UnoViewSharedPtr xUnoView(std::dynamic_pointer_cast<UnoView>(mpViewLayer));
445 if (xUnoView)
447 awt::Rectangle aCanvasArea = xUnoView->getUnoView()->getCanvasArea();
448 aAWTRect.X += aCanvasArea.X;
449 aAWTRect.Y += aCanvasArea.Y;
451 mpMediaWindow->SetPosSizePixel( Point( aAWTRect.X, aAWTRect.Y ),
452 Size( aAWTRect.Width, aAWTRect.Height ) );
454 mpMediaWindow->SetBackground( Color( COL_BLACK ) );
455 mpMediaWindow->SetParentClipMode( ParentClipMode::NoClip );
456 mpMediaWindow->EnableEraseBackground( false );
457 mpMediaWindow->EnablePaint( false );
458 mpMediaWindow->SetForwardKey( true );
459 mpMediaWindow->SetMouseTransparent( true );
460 mpMediaWindow->Show();
462 if( mxPlayer.is() )
464 aArgs[ 0 ] <<=
465 sal::static_int_cast< sal_IntPtr >( mpMediaWindow->GetParentWindowHandle() );
467 aAWTRect.X = aAWTRect.Y = 0;
468 aArgs[ 1 ] <<= aAWTRect;
469 aArgs[ 2 ] <<= reinterpret_cast< sal_IntPtr >( mpMediaWindow.get() );
471 mxPlayerWindow.set( mxPlayer->createPlayerWindow( aArgs ) );
473 if( mxPlayerWindow.is() )
475 mxPlayerWindow->setVisible( true );
476 mxPlayerWindow->setEnable( true );
480 if( !mxPlayerWindow.is() )
482 //if there was no playerwindow, then clear the mpMediaWindow too
483 //so that we can draw a placeholder instead in that space
484 mpMediaWindow.disposeAndClear();
485 mpEventHandlerParent.disposeAndClear();
490 catch( uno::RuntimeException& )
492 throw;
494 catch( uno::Exception& )
496 SAL_WARN( "slideshow", comphelper::anyToString( cppu::getCaughtException() ) );
503 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */