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