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