Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
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/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
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 .
18 : : */
19 : :
20 : :
21 : : // must be first
22 : : #include <canvas/debug.hxx>
23 : : #include <tools/diagnose_ex.h>
24 : : #include <canvas/verbosetrace.hxx>
25 : :
26 : : #include <math.h>
27 : :
28 : : #include <comphelper/anytostring.hxx>
29 : : #include <cppuhelper/exc_hlp.hxx>
30 : :
31 : : #include <vcl/window.hxx>
32 : : #include <vcl/syschild.hxx>
33 : :
34 : : #include <basegfx/tools/canvastools.hxx>
35 : : #include <basegfx/numeric/ftools.hxx>
36 : : #include <basegfx/polygon/b2dpolygon.hxx>
37 : : #include <basegfx/point/b2dpoint.hxx>
38 : : #include <basegfx/matrix/b2dhommatrix.hxx>
39 : : #include <basegfx/polygon/b2dpolygontools.hxx>
40 : : #include <basegfx/range/b2irange.hxx>
41 : : #include <canvas/canvastools.hxx>
42 : : #include <cppcanvas/vclfactory.hxx>
43 : : #include <cppcanvas/basegfxfactory.hxx>
44 : : #include <cppcanvas/basegfxfactory.hxx>
45 : : #include <avmedia/mediawindow.hxx>
46 : :
47 : : #include <com/sun/star/media/XManager.hpp>
48 : : #include <com/sun/star/media/XPlayer.hpp>
49 : : #include <com/sun/star/media/XPlayerWindow.hpp>
50 : : #include <com/sun/star/beans/XPropertySet.hpp>
51 : : #include <com/sun/star/lang/XMultiComponentFactory.hpp>
52 : : #include <com/sun/star/lang/NoSupportException.hpp>
53 : : #include <com/sun/star/awt/XWindow.hpp>
54 : : #include <com/sun/star/rendering/XCanvas.hpp>
55 : : #include <com/sun/star/lang/XComponent.hpp>
56 : :
57 : : #include "viewmediashape.hxx"
58 : : #include "mediashape.hxx"
59 : : #include "tools.hxx"
60 : : #include "unoview.hxx"
61 : :
62 : : using namespace ::com::sun::star;
63 : :
64 : : namespace slideshow
65 : : {
66 : : namespace internal
67 : : {
68 : 0 : ViewMediaShape::ViewMediaShape( const ViewLayerSharedPtr& rViewLayer,
69 : : const uno::Reference< drawing::XShape >& rxShape,
70 : : const uno::Reference< uno::XComponentContext >& rxContext ) :
71 : : mpViewLayer( rViewLayer ),
72 : : mpMediaWindow(),
73 : : maWindowOffset( 0, 0 ),
74 : : maBounds(),
75 : : mxShape( rxShape ),
76 : : mxPlayer(),
77 : : mxPlayerWindow(),
78 : : mxComponentContext( rxContext ),
79 : 0 : mbIsSoundEnabled(true)
80 : : {
81 : 0 : ENSURE_OR_THROW( mxShape.is(), "ViewMediaShape::ViewMediaShape(): Invalid Shape" );
82 : 0 : ENSURE_OR_THROW( mpViewLayer, "ViewMediaShape::ViewMediaShape(): Invalid View" );
83 : 0 : ENSURE_OR_THROW( mpViewLayer->getCanvas(), "ViewMediaShape::ViewMediaShape(): Invalid ViewLayer canvas" );
84 : 0 : ENSURE_OR_THROW( mxComponentContext.is(), "ViewMediaShape::ViewMediaShape(): Invalid component context" );
85 : :
86 : 0 : UnoViewSharedPtr pUnoView (::boost::dynamic_pointer_cast<UnoView>(rViewLayer));
87 : 0 : if (pUnoView)
88 : : {
89 : 0 : mbIsSoundEnabled = pUnoView->isSoundEnabled();
90 : 0 : }
91 : 0 : }
92 : :
93 : : // ---------------------------------------------------------------------
94 : :
95 : 0 : ViewMediaShape::~ViewMediaShape()
96 : : {
97 : : try
98 : : {
99 : 0 : endMedia();
100 : : }
101 : 0 : catch (uno::Exception &)
102 : : {
103 : : OSL_FAIL( rtl::OUStringToOString(
104 : : comphelper::anyToString(
105 : : cppu::getCaughtException() ),
106 : : RTL_TEXTENCODING_UTF8 ).getStr() );
107 : : }
108 : 0 : }
109 : :
110 : : // ---------------------------------------------------------------------
111 : :
112 : 0 : ViewLayerSharedPtr ViewMediaShape::getViewLayer() const
113 : : {
114 : 0 : return mpViewLayer;
115 : : }
116 : :
117 : : // ---------------------------------------------------------------------
118 : :
119 : 0 : bool ViewMediaShape::startMedia()
120 : : {
121 : 0 : if( !mxPlayer.is() )
122 : 0 : implInitialize( maBounds );
123 : :
124 : 0 : if( mxPlayer.is() && ( mxPlayer->getDuration() > 0.0 ) )
125 : 0 : mxPlayer->start();
126 : :
127 : 0 : return true;
128 : : }
129 : :
130 : : // ---------------------------------------------------------------------
131 : :
132 : 0 : void ViewMediaShape::endMedia()
133 : : {
134 : : // shutdown player window
135 : 0 : if( mxPlayerWindow.is() )
136 : : {
137 : 0 : uno::Reference< lang::XComponent > xComponent( mxPlayerWindow, uno::UNO_QUERY );
138 : :
139 : 0 : if( xComponent.is() )
140 : 0 : xComponent->dispose();
141 : :
142 : 0 : mxPlayerWindow.clear();
143 : : }
144 : :
145 : 0 : mpMediaWindow = ::std::auto_ptr< SystemChildWindow >();
146 : :
147 : : // shutdown player
148 : 0 : if( mxPlayer.is() )
149 : : {
150 : 0 : mxPlayer->stop();
151 : :
152 : 0 : uno::Reference< lang::XComponent > xComponent( mxPlayer, uno::UNO_QUERY );
153 : :
154 : 0 : if( xComponent.is() )
155 : 0 : xComponent->dispose();
156 : :
157 : 0 : mxPlayer.clear();
158 : : }
159 : 0 : }
160 : :
161 : : // ---------------------------------------------------------------------
162 : :
163 : 0 : void ViewMediaShape::pauseMedia()
164 : : {
165 : 0 : if( mxPlayer.is() && ( mxPlayer->getDuration() > 0.0 ) )
166 : 0 : mxPlayer->stop();
167 : 0 : }
168 : :
169 : : // ---------------------------------------------------------------------
170 : :
171 : 0 : void ViewMediaShape::setMediaTime(double fTime)
172 : : {
173 : 0 : if( mxPlayer.is() && ( mxPlayer->getDuration() > 0.0 ) )
174 : 0 : mxPlayer->setMediaTime(fTime);
175 : 0 : }
176 : :
177 : : // ---------------------------------------------------------------------
178 : :
179 : 0 : bool ViewMediaShape::render( const ::basegfx::B2DRectangle& rBounds ) const
180 : : {
181 : 0 : ::cppcanvas::CanvasSharedPtr pCanvas = mpViewLayer->getCanvas();
182 : :
183 : 0 : if( !pCanvas )
184 : 0 : return false;
185 : :
186 : 0 : if( !mpMediaWindow.get() && !mxPlayerWindow.is() )
187 : : {
188 : : // fill the shape background with black
189 : : fillRect( pCanvas,
190 : : rBounds,
191 : 0 : 0x000000FFU );
192 : : }
193 : :
194 : 0 : return true;
195 : : }
196 : :
197 : 0 : bool ViewMediaShape::resize( const ::basegfx::B2DRectangle& rNewBounds ) const
198 : : {
199 : 0 : maBounds = rNewBounds;
200 : :
201 : 0 : ::cppcanvas::CanvasSharedPtr pCanvas = mpViewLayer->getCanvas();
202 : :
203 : 0 : if( !pCanvas )
204 : 0 : return false;
205 : :
206 : 0 : if( !mxPlayerWindow.is() )
207 : 0 : return true;
208 : :
209 : 0 : uno::Reference< beans::XPropertySet > xPropSet( pCanvas->getUNOCanvas()->getDevice(),
210 : 0 : uno::UNO_QUERY );
211 : :
212 : 0 : uno::Reference< awt::XWindow > xParentWindow;
213 : 0 : if( xPropSet.is() &&
214 : : getPropertyValue( xParentWindow,
215 : : xPropSet,
216 : 0 : ::rtl::OUString("Window" )) )
217 : : {
218 : 0 : const awt::Rectangle aRect( xParentWindow->getPosSize() );
219 : :
220 : 0 : maWindowOffset.X = aRect.X;
221 : 0 : maWindowOffset.Y = aRect.Y;
222 : : }
223 : :
224 : 0 : ::basegfx::B2DRange aTmpRange;
225 : : ::canvas::tools::calcTransformedRectBounds( aTmpRange,
226 : : rNewBounds,
227 : 0 : mpViewLayer->getTransformation() );
228 : : const ::basegfx::B2IRange& rRangePix(
229 : 0 : ::basegfx::unotools::b2ISurroundingRangeFromB2DRange( aTmpRange ));
230 : :
231 : 0 : mxPlayerWindow->setEnable( !rRangePix.isEmpty() );
232 : :
233 : 0 : if( rRangePix.isEmpty() )
234 : 0 : return true;
235 : :
236 : 0 : const Point aPosPixel( rRangePix.getMinX() + maWindowOffset.X,
237 : 0 : rRangePix.getMinY() + maWindowOffset.Y );
238 : 0 : const Size aSizePixel( rRangePix.getMaxX() - rRangePix.getMinX(),
239 : 0 : rRangePix.getMaxY() - rRangePix.getMinY() );
240 : :
241 : 0 : if( mpMediaWindow.get() )
242 : : {
243 : 0 : mpMediaWindow->SetPosSizePixel( aPosPixel, aSizePixel );
244 : 0 : mxPlayerWindow->setPosSize( 0, 0,
245 : : aSizePixel.Width(), aSizePixel.Height(),
246 : 0 : 0 );
247 : : }
248 : : else
249 : : {
250 : 0 : mxPlayerWindow->setPosSize( aPosPixel.X(), aPosPixel.Y(),
251 : : aSizePixel.Width(), aSizePixel.Height(),
252 : 0 : 0 );
253 : : }
254 : :
255 : 0 : return true;
256 : : }
257 : :
258 : : // ---------------------------------------------------------------------
259 : :
260 : 0 : bool ViewMediaShape::implInitialize( const ::basegfx::B2DRectangle& rBounds )
261 : : {
262 : 0 : if( !mxPlayer.is() && mxShape.is() )
263 : : {
264 : 0 : ENSURE_OR_RETURN_FALSE( mpViewLayer->getCanvas(),
265 : : "ViewMediaShape::update(): Invalid layer canvas" );
266 : :
267 : 0 : uno::Reference< rendering::XCanvas > xCanvas( mpViewLayer->getCanvas()->getUNOCanvas() );
268 : :
269 : 0 : if( xCanvas.is() )
270 : : {
271 : 0 : uno::Reference< beans::XPropertySet > xPropSet;
272 : 0 : ::rtl::OUString aURL;
273 : :
274 : : try
275 : : {
276 : 0 : xPropSet.set( mxShape, uno::UNO_QUERY );
277 : :
278 : : // create Player
279 : 0 : if (xPropSet.is())
280 : : {
281 : 0 : if ((xPropSet->getPropertyValue(
282 : 0 : ::rtl::OUString( "PrivateTempFileURL")) >>= aURL)
283 : 0 : && !aURL.isEmpty())
284 : : {
285 : 0 : implInitializeMediaPlayer( aURL );
286 : : }
287 : 0 : else if (xPropSet->getPropertyValue(
288 : 0 : ::rtl::OUString( "MediaURL")) >>= aURL)
289 : : {
290 : 0 : implInitializeMediaPlayer( aURL );
291 : : }
292 : : }
293 : :
294 : : // create visible object
295 : 0 : uno::Sequence< uno::Any > aDeviceParams;
296 : :
297 : 0 : if( ::canvas::tools::getDeviceInfo( xCanvas, aDeviceParams ).getLength() > 1 )
298 : : {
299 : 0 : ::rtl::OUString aImplName;
300 : :
301 : 0 : aDeviceParams[ 0 ] >>= aImplName;
302 : :
303 : 0 : if( aImplName.endsWithIgnoreAsciiCaseAsciiL(
304 : 0 : RTL_CONSTASCII_STRINGPARAM("VCL") ) || aImplName.endsWithIgnoreAsciiCaseAsciiL(
305 : 0 : RTL_CONSTASCII_STRINGPARAM("Cairo") ) )
306 : : {
307 : 0 : implInitializeVCLBasedPlayerWindow( rBounds, aDeviceParams );
308 : : }
309 : 0 : else if( aImplName.endsWithIgnoreAsciiCaseAsciiL(
310 : 0 : RTL_CONSTASCII_STRINGPARAM("DX")) ||
311 : : aImplName.endsWithIgnoreAsciiCaseAsciiL(
312 : 0 : RTL_CONSTASCII_STRINGPARAM("DX9")))
313 : : {
314 : 0 : implInitializeDXBasedPlayerWindow( rBounds, aDeviceParams );
315 : 0 : }
316 : : }
317 : :
318 : : // set player properties
319 : 0 : implSetMediaProperties( xPropSet );
320 : : }
321 : 0 : catch( uno::RuntimeException& )
322 : : {
323 : 0 : throw;
324 : : }
325 : 0 : catch( uno::Exception& )
326 : : {
327 : : OSL_FAIL( rtl::OUStringToOString(
328 : : comphelper::anyToString( cppu::getCaughtException() ),
329 : : RTL_TEXTENCODING_UTF8 ).getStr() );
330 : 0 : }
331 : 0 : }
332 : : }
333 : :
334 : 0 : return mxPlayer.is() || mxPlayerWindow.is();
335 : : }
336 : :
337 : : // ---------------------------------------------------------------------
338 : :
339 : 0 : void ViewMediaShape::implSetMediaProperties( const uno::Reference< beans::XPropertySet >& rxProps )
340 : : {
341 : 0 : if( mxPlayer.is() )
342 : : {
343 : 0 : mxPlayer->setMediaTime( 0.0 );
344 : :
345 : 0 : if( rxProps.is() )
346 : : {
347 : 0 : sal_Bool bLoop( false );
348 : : getPropertyValue( bLoop,
349 : : rxProps,
350 : 0 : ::rtl::OUString( "Loop" ));
351 : 0 : mxPlayer->setPlaybackLoop( bLoop );
352 : :
353 : 0 : sal_Bool bMute( false );
354 : : getPropertyValue( bMute,
355 : : rxProps,
356 : 0 : ::rtl::OUString( "Mute" ));
357 : 0 : mxPlayer->setMute( bMute || !mbIsSoundEnabled);
358 : :
359 : 0 : sal_Int16 nVolumeDB(0);
360 : : getPropertyValue( nVolumeDB,
361 : : rxProps,
362 : 0 : ::rtl::OUString( "VolumeDB" ));
363 : 0 : mxPlayer->setVolumeDB( nVolumeDB );
364 : :
365 : 0 : if( mxPlayerWindow.is() )
366 : : {
367 : 0 : media::ZoomLevel eZoom(media::ZoomLevel_FIT_TO_WINDOW);
368 : : getPropertyValue( eZoom,
369 : : rxProps,
370 : 0 : ::rtl::OUString( "Zoom" ));
371 : 0 : mxPlayerWindow->setZoomLevel( eZoom );
372 : : }
373 : : }
374 : : }
375 : 0 : }
376 : :
377 : : // ---------------------------------------------------------------------
378 : :
379 : 0 : void ViewMediaShape::implInitializeMediaPlayer( const ::rtl::OUString& rMediaURL )
380 : : {
381 : 0 : if( !mxPlayer.is() )
382 : : {
383 : : try
384 : : {
385 : 0 : if( !rMediaURL.isEmpty() )
386 : : {
387 : : mxPlayer.set( avmedia::MediaWindow::createPlayer( rMediaURL ),
388 : 0 : uno::UNO_QUERY );
389 : : }
390 : : }
391 : 0 : catch( uno::RuntimeException& )
392 : : {
393 : 0 : throw;
394 : : }
395 : 0 : catch( const uno::Exception& )
396 : : {
397 : : throw lang::NoSupportException(
398 : : rtl::OUString( "No video support for " ) + rMediaURL,
399 : 0 : uno::Reference<uno::XInterface>() );
400 : : }
401 : : }
402 : 0 : }
403 : :
404 : : // ---------------------------------------------------------------------
405 : :
406 : 0 : bool ViewMediaShape::implInitializeVCLBasedPlayerWindow( const ::basegfx::B2DRectangle& rBounds,
407 : : const uno::Sequence< uno::Any >& rVCLDeviceParams)
408 : : {
409 : : OSL_TRACE( "ViewMediaShape::implInitializeVCLBasedPlayerWindow" );
410 : 0 : if( !mpMediaWindow.get() && !rBounds.isEmpty() )
411 : : {
412 : : try
413 : : {
414 : 0 : sal_Int64 aVal=0;
415 : :
416 : 0 : rVCLDeviceParams[ 1 ] >>= aVal;
417 : :
418 : 0 : Window* pWindow = reinterpret_cast< Window* >( aVal );
419 : :
420 : 0 : if( pWindow )
421 : : {
422 : 0 : ::basegfx::B2DRange aTmpRange;
423 : : ::canvas::tools::calcTransformedRectBounds( aTmpRange,
424 : : rBounds,
425 : 0 : mpViewLayer->getTransformation() );
426 : : const ::basegfx::B2IRange& rRangePix(
427 : 0 : ::basegfx::unotools::b2ISurroundingRangeFromB2DRange( aTmpRange ));
428 : :
429 : 0 : if( !rRangePix.isEmpty() )
430 : : {
431 : 0 : uno::Sequence< uno::Any > aArgs( 3 );
432 : 0 : awt::Rectangle aAWTRect( rRangePix.getMinX(),
433 : 0 : rRangePix.getMinY(),
434 : 0 : rRangePix.getMaxX() - rRangePix.getMinX(),
435 : 0 : rRangePix.getMaxY() - rRangePix.getMinY() );
436 : :
437 : : mpMediaWindow = ::std::auto_ptr< SystemChildWindow >( new
438 : 0 : SystemChildWindow( pWindow, WB_CLIPCHILDREN ) );
439 : 0 : mpMediaWindow->SetBackground( Color( COL_BLACK ) );
440 : 0 : mpMediaWindow->SetPosSizePixel( Point( aAWTRect.X, aAWTRect.Y ),
441 : 0 : Size( aAWTRect.Width, aAWTRect.Height ) );
442 : 0 : mpMediaWindow->SetParentClipMode( PARENTCLIPMODE_NOCLIP );
443 : 0 : mpMediaWindow->EnableEraseBackground( sal_False );
444 : 0 : mpMediaWindow->EnablePaint( sal_False );
445 : 0 : mpMediaWindow->SetForwardKey( sal_True );
446 : 0 : mpMediaWindow->SetMouseTransparent( sal_True );
447 : 0 : mpMediaWindow->Show();
448 : :
449 : 0 : if( mxPlayer.is() )
450 : : {
451 : 0 : aArgs[ 0 ] = uno::makeAny(
452 : 0 : sal::static_int_cast< sal_IntPtr >( mpMediaWindow->GetParentWindowHandle() ) );
453 : :
454 : 0 : aAWTRect.X = aAWTRect.Y = 0;
455 : 0 : aArgs[ 1 ] = uno::makeAny( aAWTRect );
456 : :
457 : 0 : aArgs[ 2 ] = uno::makeAny( reinterpret_cast< sal_IntPtr >( mpMediaWindow.get() ) );
458 : :
459 : 0 : mxPlayerWindow.set( mxPlayer->createPlayerWindow( aArgs ) );
460 : :
461 : 0 : if( mxPlayerWindow.is() )
462 : : {
463 : 0 : mxPlayerWindow->setVisible( true );
464 : 0 : mxPlayerWindow->setEnable( true );
465 : : }
466 : 0 : }
467 : : }
468 : : }
469 : : }
470 : 0 : catch( uno::RuntimeException& )
471 : : {
472 : 0 : throw;
473 : : }
474 : 0 : catch( uno::Exception& )
475 : : {
476 : : OSL_FAIL( rtl::OUStringToOString(
477 : : comphelper::anyToString( cppu::getCaughtException() ),
478 : : RTL_TEXTENCODING_UTF8 ).getStr() );
479 : : }
480 : : }
481 : :
482 : 0 : return mxPlayerWindow.is();
483 : : }
484 : :
485 : : // ---------------------------------------------------------------------
486 : :
487 : 0 : bool ViewMediaShape::implInitializeDXBasedPlayerWindow( const ::basegfx::B2DRectangle& rBounds,
488 : : const uno::Sequence< uno::Any >& rDXDeviceParams )
489 : : {
490 : 0 : if( !mxPlayerWindow.is() )
491 : : {
492 : : try
493 : : {
494 : 0 : if( rDXDeviceParams.getLength() == 2 )
495 : : {
496 : 0 : sal_Int64 aWNDVal=0;
497 : :
498 : 0 : rDXDeviceParams[ 1 ] >>= aWNDVal;
499 : :
500 : 0 : if( aWNDVal )
501 : : {
502 : 0 : ::basegfx::B2DRange aTmpRange;
503 : : ::canvas::tools::calcTransformedRectBounds( aTmpRange,
504 : : rBounds,
505 : 0 : mpViewLayer->getTransformation() );
506 : : const ::basegfx::B2IRange& rRangePix(
507 : 0 : ::basegfx::unotools::b2ISurroundingRangeFromB2DRange( aTmpRange ));
508 : :
509 : 0 : if( !rRangePix.isEmpty() )
510 : : {
511 : 0 : uno::Sequence< uno::Any > aArgs( 2 );
512 : 0 : awt::Rectangle aAWTRect( rRangePix.getMinX() + maWindowOffset.X,
513 : 0 : rRangePix.getMinY() + maWindowOffset.Y,
514 : 0 : rRangePix.getMaxX() - rRangePix.getMinX(),
515 : 0 : rRangePix.getMaxY() - rRangePix.getMinY() );
516 : :
517 : 0 : if( mxPlayer.is() )
518 : : {
519 : 0 : aArgs[ 0 ] = uno::makeAny( sal::static_int_cast< sal_Int32 >( aWNDVal) );
520 : 0 : aArgs[ 1 ] = uno::makeAny( aAWTRect );
521 : :
522 : 0 : mxPlayerWindow.set( mxPlayer->createPlayerWindow( aArgs ) );
523 : 0 : }
524 : : }
525 : : }
526 : : }
527 : : }
528 : 0 : catch( uno::RuntimeException& )
529 : : {
530 : 0 : throw;
531 : : }
532 : 0 : catch( uno::Exception& )
533 : : {
534 : : OSL_FAIL( rtl::OUStringToOString(
535 : : comphelper::anyToString( cppu::getCaughtException() ),
536 : : RTL_TEXTENCODING_UTF8 ).getStr() );
537 : : }
538 : : }
539 : :
540 : 0 : return mxPlayerWindow.is();
541 : : }
542 : : }
543 : : }
544 : :
545 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|