1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <canvas/debug.hxx>
23 #include <tools/diagnose_ex.h>
24 #include <canvas/verbosetrace.hxx>
28 #include <comphelper/anytostring.hxx>
29 #include <cppuhelper/exc_hlp.hxx>
31 #include <vcl/canvastools.hxx>
32 #include <vcl/syschild.hxx>
33 #include <vcl/sysdata.hxx>
34 #include <vcl/window.hxx>
35 #include <vcl/graph.hxx>
37 #include <basegfx/tools/canvastools.hxx>
38 #include <basegfx/matrix/b2dhommatrixtools.hxx>
39 #include <basegfx/numeric/ftools.hxx>
40 #include <basegfx/polygon/b2dpolygon.hxx>
41 #include <basegfx/point/b2dpoint.hxx>
42 #include <basegfx/matrix/b2dhommatrix.hxx>
43 #include <basegfx/polygon/b2dpolygontools.hxx>
44 #include <basegfx/range/b2irange.hxx>
45 #include <canvas/canvastools.hxx>
46 #include <cppcanvas/vclfactory.hxx>
47 #include <cppcanvas/basegfxfactory.hxx>
48 #include <avmedia/mediawindow.hxx>
49 #include <avmedia/modeltools.hxx>
51 #include <vcl/opengl/OpenGLContext.hxx>
53 #include <com/sun/star/media/XManager.hpp>
54 #include <com/sun/star/media/XPlayer.hpp>
55 #include <com/sun/star/media/XPlayerWindow.hpp>
56 #include <com/sun/star/beans/XPropertySet.hpp>
57 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
58 #include <com/sun/star/lang/NoSupportException.hpp>
59 #include <com/sun/star/awt/XWindow.hpp>
60 #include <com/sun/star/rendering/XCanvas.hpp>
61 #include <com/sun/star/lang/XComponent.hpp>
63 #include "viewmediashape.hxx"
64 #include "mediashape.hxx"
66 #include "unoview.hxx"
68 using namespace ::com::sun::star
;
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(0),
79 maWindowOffset( 0, 0 ),
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
pUnoView (::boost::dynamic_pointer_cast
<UnoView
>(rViewLayer
));
95 mbIsSoundEnabled
= pUnoView
->isSoundEnabled();
101 ViewMediaShape::~ViewMediaShape()
107 catch (uno::Exception
&)
109 OSL_FAIL( OUStringToOString(
110 comphelper::anyToString(
111 cppu::getCaughtException() ),
112 RTL_TEXTENCODING_UTF8
).getStr() );
118 ViewLayerSharedPtr
ViewMediaShape::getViewLayer() const
125 bool ViewMediaShape::startMedia()
128 implInitialize( maBounds
);
138 void ViewMediaShape::endMedia()
140 // shutdown player window
141 if( mxPlayerWindow
.is() )
143 uno::Reference
< lang::XComponent
> xComponent( mxPlayerWindow
, uno::UNO_QUERY
);
145 if( xComponent
.is() )
146 xComponent
->dispose();
148 mxPlayerWindow
.clear();
151 mpMediaWindow
.disposeAndClear();
152 mpEventHandlerParent
.disposeAndClear();
159 uno::Reference
< lang::XComponent
> xComponent( mxPlayer
, uno::UNO_QUERY
);
161 if( xComponent
.is() )
162 xComponent
->dispose();
170 void ViewMediaShape::pauseMedia()
178 void ViewMediaShape::setMediaTime(double fTime
)
181 mxPlayer
->setMediaTime(fTime
);
186 bool ViewMediaShape::render( const ::basegfx::B2DRectangle
& rBounds
) const
188 #if !HAVE_FEATURE_AVMEDIA
191 ::cppcanvas::CanvasSharedPtr pCanvas
= mpViewLayer
->getCanvas();
196 if( !mpMediaWindow
.get() && !mxPlayerWindow
.is() )
198 uno::Reference
< graphic::XGraphic
> xGraphic
;
199 uno::Reference
< beans::XPropertySet
> xPropSet( mxShape
, uno::UNO_QUERY
);
202 xPropSet
->getPropertyValue("FallbackGraphic") >>= xGraphic
;
205 Graphic
aGraphic(xGraphic
);
206 const BitmapEx aBmp
= aGraphic
.GetBitmapEx();
208 uno::Reference
< rendering::XBitmap
> xBitmap(vcl::unotools::xBitmapFromBitmapEx(
209 pCanvas
->getUNOCanvas()->getDevice(), aBmp
));
211 rendering::ViewState aViewState
;
212 aViewState
.AffineTransform
= pCanvas
->getViewState().AffineTransform
;
214 rendering::RenderState aRenderState
;
215 ::canvas::tools::initRenderState( aRenderState
);
217 const ::Size
aBmpSize( aBmp
.GetSizePixel() );
219 const ::basegfx::B2DVector
aScale( rBounds
.getWidth() / aBmpSize
.Width(),
220 rBounds
.getHeight() / aBmpSize
.Height() );
221 const basegfx::B2DHomMatrix
aTranslation(basegfx::tools::createScaleTranslateB2DHomMatrix(
222 aScale
, rBounds
.getMinimum()));
223 ::canvas::tools::setRenderStateTransform( aRenderState
, aTranslation
);
225 pCanvas
->getUNOCanvas()->drawBitmap( xBitmap
,
233 bool ViewMediaShape::resize( const ::basegfx::B2DRectangle
& rNewBounds
) const
235 maBounds
= rNewBounds
;
237 ::cppcanvas::CanvasSharedPtr pCanvas
= mpViewLayer
->getCanvas();
242 if( !mxPlayerWindow
.is() )
245 uno::Reference
< beans::XPropertySet
> xPropSet( pCanvas
->getUNOCanvas()->getDevice(),
248 uno::Reference
< awt::XWindow
> xParentWindow
;
250 getPropertyValue( xParentWindow
,
252 OUString("Window" )) )
254 const awt::Rectangle
aRect( xParentWindow
->getPosSize() );
256 maWindowOffset
.X
= aRect
.X
;
257 maWindowOffset
.Y
= aRect
.Y
;
260 ::basegfx::B2DRange aTmpRange
;
261 ::canvas::tools::calcTransformedRectBounds( aTmpRange
,
263 mpViewLayer
->getTransformation() );
264 const ::basegfx::B2IRange
& rRangePix(
265 ::basegfx::unotools::b2ISurroundingRangeFromB2DRange( aTmpRange
));
267 mxPlayerWindow
->setEnable( !rRangePix
.isEmpty() );
269 if( rRangePix
.isEmpty() )
272 const Point
aPosPixel( rRangePix
.getMinX() + maWindowOffset
.X
,
273 rRangePix
.getMinY() + maWindowOffset
.Y
);
274 const Size
aSizePixel( rRangePix
.getMaxX() - rRangePix
.getMinX(),
275 rRangePix
.getMaxY() - rRangePix
.getMinY() );
277 if( mpMediaWindow
.get() )
279 if( mpEventHandlerParent
)
281 mpEventHandlerParent
->SetPosSizePixel( aPosPixel
, aSizePixel
);
282 mpMediaWindow
->SetPosSizePixel( Point(0,0), aSizePixel
);
286 mpMediaWindow
->SetPosSizePixel( aPosPixel
, aSizePixel
);
288 mxPlayerWindow
->setPosSize( 0, 0,
289 aSizePixel
.Width(), aSizePixel
.Height(),
294 mxPlayerWindow
->setPosSize( aPosPixel
.X(), aPosPixel
.Y(),
295 aSizePixel
.Width(), aSizePixel
.Height(),
304 bool ViewMediaShape::implInitialize( const ::basegfx::B2DRectangle
& rBounds
)
306 if( !mxPlayer
.is() && mxShape
.is() )
308 ENSURE_OR_RETURN_FALSE( mpViewLayer
->getCanvas(),
309 "ViewMediaShape::implInitialize(): Invalid layer canvas" );
311 uno::Reference
< rendering::XCanvas
> xCanvas( mpViewLayer
->getCanvas()->getUNOCanvas() );
315 uno::Reference
< beans::XPropertySet
> xPropSet
;
318 xPropSet
.set( mxShape
, uno::UNO_QUERY
);
325 xPropSet
->getPropertyValue("MediaMimeType") >>= sMimeType
;
326 if ((xPropSet
->getPropertyValue(
327 OUString( "PrivateTempFileURL")) >>= aURL
)
330 implInitializeMediaPlayer( aURL
, sMimeType
);
332 else if (xPropSet
->getPropertyValue(
333 OUString( "MediaURL")) >>= aURL
)
335 implInitializeMediaPlayer( aURL
, sMimeType
);
339 // create visible object
340 uno::Sequence
< uno::Any
> aDeviceParams
;
342 if( ::canvas::tools::getDeviceInfo( xCanvas
, aDeviceParams
).getLength() > 1 )
344 implInitializePlayerWindow( rBounds
, aDeviceParams
, sMimeType
);
347 // set player properties
348 implSetMediaProperties( xPropSet
);
350 catch( uno::RuntimeException
& )
354 catch( uno::Exception
& )
356 OSL_FAIL( OUStringToOString(
357 comphelper::anyToString( cppu::getCaughtException() ),
358 RTL_TEXTENCODING_UTF8
).getStr() );
363 return mxPlayer
.is() || mxPlayerWindow
.is();
368 void ViewMediaShape::implSetMediaProperties( const uno::Reference
< beans::XPropertySet
>& rxProps
)
372 mxPlayer
->setMediaTime( 0.0 );
377 getPropertyValue( bLoop
,
380 mxPlayer
->setPlaybackLoop( bLoop
);
383 getPropertyValue( bMute
,
386 mxPlayer
->setMute( bMute
|| !mbIsSoundEnabled
);
388 sal_Int16
nVolumeDB(0);
389 getPropertyValue( nVolumeDB
,
391 OUString( "VolumeDB" ));
392 mxPlayer
->setVolumeDB( nVolumeDB
);
394 if( mxPlayerWindow
.is() )
396 media::ZoomLevel
eZoom(media::ZoomLevel_FIT_TO_WINDOW
);
397 getPropertyValue( eZoom
,
400 mxPlayerWindow
->setZoomLevel( eZoom
);
408 void ViewMediaShape::implInitializeMediaPlayer( const OUString
& rMediaURL
, const OUString
& rMimeType
)
410 #if !HAVE_FEATURE_AVMEDIA
418 if( !rMediaURL
.isEmpty() )
420 mxPlayer
.set( avmedia::MediaWindow::createPlayer( rMediaURL
, ""/*TODO!*/, &rMimeType
),
424 catch( uno::RuntimeException
& )
428 catch( const uno::Exception
& )
430 throw lang::NoSupportException( "No video support for " + rMediaURL
);
438 bool ViewMediaShape::implInitializePlayerWindow( const ::basegfx::B2DRectangle
& rBounds
,
439 const uno::Sequence
< uno::Any
>& rVCLDeviceParams
,
440 const OUString
& rMimeType
)
442 OSL_TRACE( "ViewMediaShape::implInitializePlayerWindow" );
443 if( !mpMediaWindow
.get() && !rBounds
.isEmpty() )
449 rVCLDeviceParams
[ 1 ] >>= aVal
;
451 vcl::Window
* pWindow
= reinterpret_cast< vcl::Window
* >( aVal
);
455 ::basegfx::B2DRange aTmpRange
;
456 ::canvas::tools::calcTransformedRectBounds( aTmpRange
,
458 mpViewLayer
->getTransformation() );
459 const ::basegfx::B2IRange
& rRangePix(
460 ::basegfx::unotools::b2ISurroundingRangeFromB2DRange( aTmpRange
));
462 if( !rRangePix
.isEmpty() )
464 uno::Sequence
< uno::Any
> aArgs( 3 );
465 awt::Rectangle
aAWTRect( rRangePix
.getMinX(),
467 rRangePix
.getMaxX() - rRangePix
.getMinX(),
468 rRangePix
.getMaxY() - rRangePix
.getMinY() );
469 #if !HAVE_FEATURE_GLTF
472 if( avmedia::IsModel(rMimeType
) )
474 mpMediaWindow
.disposeAndClear();
475 mpEventHandlerParent
.disposeAndClear();
476 mpEventHandlerParent
= VclPtr
<vcl::Window
>::Create(pWindow
, WB_NOBORDER
|WB_NODIALOGCONTROL
);
477 mpEventHandlerParent
->SetPosSizePixel( Point( aAWTRect
.X
, aAWTRect
.Y
),
478 Size( aAWTRect
.Width
, aAWTRect
.Height
) );
479 mpEventHandlerParent
->EnablePaint(false);
480 mpEventHandlerParent
->Show();
481 SystemWindowData aWinData
= OpenGLContext::generateWinData(mpEventHandlerParent
.get(), false);
482 mpMediaWindow
= VclPtr
<SystemChildWindow
>::Create(mpEventHandlerParent
.get(), 0, &aWinData
);
483 mpMediaWindow
->SetPosSizePixel( Point( 0, 0 ),
484 Size( aAWTRect
.Width
, aAWTRect
.Height
) );
489 mpMediaWindow
.disposeAndClear();
490 mpMediaWindow
= VclPtr
<SystemChildWindow
>::Create( pWindow
, WB_CLIPCHILDREN
);
491 mpMediaWindow
->SetPosSizePixel( Point( aAWTRect
.X
, aAWTRect
.Y
),
492 Size( aAWTRect
.Width
, aAWTRect
.Height
) );
494 mpMediaWindow
->SetBackground( Color( COL_BLACK
) );
495 mpMediaWindow
->SetParentClipMode( PARENTCLIPMODE_NOCLIP
);
496 mpMediaWindow
->EnableEraseBackground( false );
497 mpMediaWindow
->EnablePaint( false );
498 mpMediaWindow
->SetForwardKey( true );
499 mpMediaWindow
->SetMouseTransparent( true );
500 mpMediaWindow
->Show();
504 aArgs
[ 0 ] = uno::makeAny(
505 sal::static_int_cast
< sal_IntPtr
>( mpMediaWindow
->GetParentWindowHandle() ) );
507 aAWTRect
.X
= aAWTRect
.Y
= 0;
508 aArgs
[ 1 ] = uno::makeAny( aAWTRect
);
509 aArgs
[ 2 ] = uno::makeAny( reinterpret_cast< sal_IntPtr
>( mpMediaWindow
.get() ) );
511 mxPlayerWindow
.set( mxPlayer
->createPlayerWindow( aArgs
) );
513 if( mxPlayerWindow
.is() )
515 mxPlayerWindow
->setVisible( true );
516 mxPlayerWindow
->setEnable( true );
520 if( !mxPlayerWindow
.is() )
522 //if there was no playerwindow, then clear the mpMediaWindow too
523 //so that we can draw a placeholder instead in that space
524 mpMediaWindow
.disposeAndClear();
525 mpEventHandlerParent
.disposeAndClear();
530 catch( uno::RuntimeException
& )
534 catch( uno::Exception
& )
536 OSL_FAIL( OUStringToOString(
537 comphelper::anyToString( cppu::getCaughtException() ),
538 RTL_TEXTENCODING_UTF8
).getStr() );
542 return mxPlayerWindow
.is();
547 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */