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>
23 #include "mediawindow_impl.hxx"
24 #include "mediaevent_impl.hxx"
25 #include <mediamisc.hxx>
26 #include <bitmaps.hlst>
32 #include <sal/log.hxx>
33 #include <comphelper/processfactory.hxx>
34 #include <tools/urlobj.hxx>
35 #include <unotools/securityoptions.hxx>
36 #include <vcl/svapp.hxx>
37 #include <vcl/commandevent.hxx>
38 #include <vcl/event.hxx>
39 #include <vcl/ptrstyle.hxx>
41 #include <com/sun/star/awt/SystemPointer.hpp>
42 #include <com/sun/star/lang/XComponent.hpp>
43 #include <com/sun/star/media/XManager.hpp>
44 #include <com/sun/star/uno/XComponentContext.hpp>
45 #include <vcl/sysdata.hxx>
46 #if HAVE_FEATURE_OPENGL
47 #include <vcl/opengl/OpenGLContext.hxx>
49 using namespace ::com::sun::star
;
51 namespace avmedia
{ namespace priv
{
53 MediaWindowControl::MediaWindowControl(vcl::Window
* pParent
)
54 : MediaControl(pParent
, MEDIACONTROLSTYLE_MULTILINE
)
58 void MediaWindowControl::update()
62 static_cast< MediaWindowImpl
* >( GetParent() )->updateMediaItem( aItem
);
66 void MediaWindowControl::execute(const MediaItem
& rItem
)
68 static_cast<MediaWindowImpl
*>(GetParent())->executeMediaItem(rItem
);
71 MediaChildWindow::MediaChildWindow(vcl::Window
* pParent
)
72 : SystemChildWindow(pParent
, WB_CLIPCHILDREN
)
76 void MediaChildWindow::MouseMove( const MouseEvent
& rMEvt
)
78 const MouseEvent
aTransformedEvent( GetParent()->ScreenToOutputPixel( OutputToScreenPixel( rMEvt
.GetPosPixel() ) ),
79 rMEvt
.GetClicks(), rMEvt
.GetMode(), rMEvt
.GetButtons(), rMEvt
.GetModifier() );
81 SystemChildWindow::MouseMove( rMEvt
);
82 GetParent()->MouseMove( aTransformedEvent
);
85 void MediaChildWindow::MouseButtonDown( const MouseEvent
& rMEvt
)
87 const MouseEvent
aTransformedEvent( GetParent()->ScreenToOutputPixel( OutputToScreenPixel( rMEvt
.GetPosPixel() ) ),
88 rMEvt
.GetClicks(), rMEvt
.GetMode(), rMEvt
.GetButtons(), rMEvt
.GetModifier() );
90 SystemChildWindow::MouseButtonDown( rMEvt
);
91 GetParent()->MouseButtonDown( aTransformedEvent
);
94 void MediaChildWindow::MouseButtonUp( const MouseEvent
& rMEvt
)
96 const MouseEvent
aTransformedEvent( GetParent()->ScreenToOutputPixel( OutputToScreenPixel( rMEvt
.GetPosPixel() ) ),
97 rMEvt
.GetClicks(), rMEvt
.GetMode(), rMEvt
.GetButtons(), rMEvt
.GetModifier() );
99 SystemChildWindow::MouseButtonUp( rMEvt
);
100 GetParent()->MouseButtonUp( aTransformedEvent
);
103 void MediaChildWindow::KeyInput( const KeyEvent
& rKEvt
)
105 SystemChildWindow::KeyInput( rKEvt
);
106 GetParent()->KeyInput( rKEvt
);
109 void MediaChildWindow::KeyUp( const KeyEvent
& rKEvt
)
111 SystemChildWindow::KeyUp( rKEvt
);
112 GetParent()->KeyUp( rKEvt
);
115 void MediaChildWindow::Command( const CommandEvent
& rCEvt
)
117 const CommandEvent
aTransformedEvent( GetParent()->ScreenToOutputPixel( OutputToScreenPixel( rCEvt
.GetMousePosPixel() ) ),
118 rCEvt
.GetCommand(), rCEvt
.IsMouseEvent(), rCEvt
.GetEventData() );
120 SystemChildWindow::Command( rCEvt
);
121 GetParent()->Command( aTransformedEvent
);
124 MediaWindowImpl::MediaWindowImpl(vcl::Window
* pParent
, MediaWindow
* pMediaWindow
, bool bInternalMediaControl
)
126 , DropTargetHelper(this)
127 , DragSourceHelper(this)
128 , mpMediaWindow(pMediaWindow
)
129 , mpMediaWindowControl(bInternalMediaControl
? VclPtr
<MediaWindowControl
>::Create(this) : nullptr)
131 if (mpMediaWindowControl
)
133 mpMediaWindowControl
->SetSizePixel(mpMediaWindowControl
->getMinSizePixel());
134 mpMediaWindowControl
->Show();
138 MediaWindowImpl::~MediaWindowImpl()
143 void MediaWindowImpl::dispose()
148 if (mxPlayerWindow
.is())
150 auto pEventsIf
= static_cast<cppu::OWeakObject
*>(mxEvents
.get());
151 mxPlayerWindow
->removeKeyListener( uno::Reference
< awt::XKeyListener
>( pEventsIf
, uno::UNO_QUERY
) );
152 mxPlayerWindow
->removeMouseListener( uno::Reference
< awt::XMouseListener
>( pEventsIf
, uno::UNO_QUERY
) );
153 mxPlayerWindow
->removeMouseMotionListener( uno::Reference
< awt::XMouseMotionListener
>( pEventsIf
, uno::UNO_QUERY
) );
155 uno::Reference
< lang::XComponent
> xComponent( mxPlayerWindow
, uno::UNO_QUERY
);
157 xComponent
->dispose();
159 mxPlayerWindow
.clear();
162 uno::Reference
< lang::XComponent
> xComponent( mxPlayer
, uno::UNO_QUERY
);
163 if (xComponent
.is()) // this stops the player
164 xComponent
->dispose();
168 mpMediaWindow
= nullptr;
170 mpEmptyBmpEx
.reset();
171 mpAudioBmpEx
.reset();
172 mpMediaWindowControl
.disposeAndClear();
173 mpChildWindow
.disposeAndClear();
178 uno::Reference
<media::XPlayer
> MediaWindowImpl::createPlayer(const OUString
& rURL
, const OUString
& rReferer
, const OUString
* pMimeType
)
180 uno::Reference
<media::XPlayer
> xPlayer
;
185 if (SvtSecurityOptions().isUntrustedReferer(rReferer
))
189 uno::Reference
<uno::XComponentContext
> xContext(::comphelper::getProcessComponentContext());
191 if (!pMimeType
|| *pMimeType
== AVMEDIA_MIMETYPE_COMMON
)
194 static const char * aServiceManagers
[] =
196 AVMEDIA_MANAGER_SERVICE_PREFERRED
,
197 AVMEDIA_MANAGER_SERVICE_NAME
,
198 // a fallback path just for gstreamer which has
199 // two significant versions deployed at once ...
200 #ifdef AVMEDIA_MANAGER_SERVICE_NAME_OLD
201 AVMEDIA_MANAGER_SERVICE_NAME_OLD
205 for (sal_uInt32 i
= 0; !xPlayer
.is() && i
< SAL_N_ELEMENTS( aServiceManagers
); ++i
)
207 const OUString
aServiceName(aServiceManagers
[i
],
208 strlen( aServiceManagers
[i
]),
209 RTL_TEXTENCODING_ASCII_US
);
211 xPlayer
= createPlayer(rURL
, aServiceName
, xContext
);
218 uno::Reference
< media::XPlayer
> MediaWindowImpl::createPlayer(
219 const OUString
& rURL
, const OUString
& rManagerServName
,
220 const uno::Reference
< uno::XComponentContext
>& xContext
)
222 uno::Reference
< media::XPlayer
> xPlayer
;
225 uno::Reference
< media::XManager
> xManager (
226 xContext
->getServiceManager()->createInstanceWithContext(rManagerServName
, xContext
),
229 xPlayer
.set( xManager
->createPlayer( rURL
), uno::UNO_QUERY
);
231 SAL_INFO( "avmedia", "failed to create media player service " << rManagerServName
);
232 } catch ( const uno::Exception
&e
)
234 SAL_WARN( "avmedia", "couldn't create media player " << rManagerServName
<< ", " << e
);
239 void MediaWindowImpl::setURL( const OUString
& rURL
,
240 OUString
const& rTempURL
, OUString
const& rReferer
)
242 maReferer
= rReferer
;
243 if( rURL
!= getURL() )
248 if( mxPlayerWindow
.is() )
250 mxPlayerWindow
->setVisible( false );
251 mxPlayerWindow
.clear();
255 mTempFileURL
.clear();
257 if (!rTempURL
.isEmpty())
260 mTempFileURL
= rTempURL
;
264 INetURLObject
aURL( rURL
);
266 if (aURL
.GetProtocol() != INetProtocol::NotValid
)
267 maFileURL
= aURL
.GetMainURL(INetURLObject::DecodeMechanism::Unambiguous
);
272 mxPlayer
= createPlayer((!mTempFileURL
.isEmpty()) ? mTempFileURL
: maFileURL
, rReferer
, &m_sMimeType
);
277 const OUString
& MediaWindowImpl::getURL() const
282 bool MediaWindowImpl::isValid() const
284 return mxPlayer
.is();
287 Size
MediaWindowImpl::getPreferredSize() const
293 awt::Size
aPrefSize( mxPlayer
->getPreferredPlayerWindowSize() );
295 aRet
.setWidth( aPrefSize
.Width
);
296 aRet
.setHeight( aPrefSize
.Height
);
302 bool MediaWindowImpl::start()
304 return mxPlayer
.is() && ( mxPlayer
->start(), true );
307 void MediaWindowImpl::updateMediaItem( MediaItem
& rItem
) const
310 rItem
.setState( MediaState::Play
);
312 rItem
.setState( ( getMediaTime() == 0.0 ) ? MediaState::Stop
: MediaState::Pause
);
314 rItem
.setDuration( getDuration() );
315 rItem
.setTime( getMediaTime() );
316 rItem
.setLoop( mxPlayer
.is() && mxPlayer
->isPlaybackLoop() );
317 rItem
.setMute( mxPlayer
.is() && mxPlayer
->isMute() );
318 rItem
.setVolumeDB( mxPlayer
.is() ? mxPlayer
->getVolumeDB() : 0 );
319 rItem
.setZoom( mxPlayerWindow
.is() ? mxPlayerWindow
->getZoomLevel() : media::ZoomLevel_NOT_AVAILABLE
);
320 rItem
.setURL( getURL(), mTempFileURL
, maReferer
);
323 void MediaWindowImpl::executeMediaItem( const MediaItem
& rItem
)
325 const AVMediaSetMask nMaskSet
= rItem
.getMaskSet();
328 if (nMaskSet
& AVMediaSetMask::URL
)
330 m_sMimeType
= rItem
.getMimeType();
331 setURL(rItem
.getURL(), rItem
.getTempURL(), rItem
.getReferer());
334 // set different states next
335 if (nMaskSet
& AVMediaSetMask::TIME
)
336 setMediaTime(std::min(rItem
.getTime(), getDuration()));
338 if (nMaskSet
& AVMediaSetMask::LOOP
&& mxPlayer
.is() )
339 mxPlayer
->setPlaybackLoop( rItem
.isLoop() );
341 if (nMaskSet
& AVMediaSetMask::MUTE
&& mxPlayer
.is() )
342 mxPlayer
->setMute( rItem
.isMute() );
344 if (nMaskSet
& AVMediaSetMask::VOLUMEDB
&& mxPlayer
.is() )
345 mxPlayer
->setVolumeDB( rItem
.getVolumeDB() );
347 if (nMaskSet
& AVMediaSetMask::ZOOM
&& mxPlayerWindow
.is() )
348 mxPlayerWindow
->setZoomLevel( rItem
.getZoom() );
350 // set play state at last
351 if (nMaskSet
& AVMediaSetMask::STATE
)
353 switch (rItem
.getState())
355 case MediaState::Play
:
362 case MediaState::Pause
:
369 case MediaState::Stop
:
383 void MediaWindowImpl::stop()
389 bool MediaWindowImpl::isPlaying() const
391 return( mxPlayer
.is() && mxPlayer
->isPlaying() );
394 double MediaWindowImpl::getDuration() const
396 return( mxPlayer
.is() ? mxPlayer
->getDuration() : 0.0 );
399 void MediaWindowImpl::setMediaTime( double fTime
)
402 mxPlayer
->setMediaTime( fTime
);
405 double MediaWindowImpl::getMediaTime() const
407 return( mxPlayer
.is() ? mxPlayer
->getMediaTime() : 0.0 );
410 void MediaWindowImpl::stopPlayingInternal(bool bStop
)
414 bStop
? mxPlayer
->stop() : mxPlayer
->start();
418 void MediaWindowImpl::onURLChanged()
420 if (m_sMimeType
== AVMEDIA_MIMETYPE_COMMON
)
422 mpChildWindow
.disposeAndClear();
423 mpChildWindow
.reset(VclPtr
<MediaChildWindow
>::Create(this));
427 mpChildWindow
->SetHelpId(HID_AVMEDIA_PLAYERWINDOW
);
428 mxEvents
= new MediaEventListenersImpl(*mpChildWindow
);
433 uno::Sequence
<uno::Any
> aArgs( 3 );
434 uno::Reference
<media::XPlayerWindow
> xPlayerWindow
;
436 const Size
aSize(mpChildWindow
->GetSizePixel());
438 aArgs
[0] <<= mpChildWindow
->GetParentWindowHandle();
439 aArgs
[1] <<= awt::Rectangle(aPoint
.X(), aPoint
.Y(), aSize
.Width(), aSize
.Height());
440 aArgs
[2] <<= reinterpret_cast<sal_IntPtr
>(mpChildWindow
.get());
444 xPlayerWindow
= mxPlayer
->createPlayerWindow( aArgs
);
446 catch( const uno::RuntimeException
& )
448 // happens eg, on MacOSX where Java frames cannot be created from X11 window handles
451 mxPlayerWindow
= xPlayerWindow
;
453 if( xPlayerWindow
.is() )
455 auto pEventsIf
= static_cast<cppu::OWeakObject
*>(mxEvents
.get());
456 xPlayerWindow
->addKeyListener( uno::Reference
< awt::XKeyListener
>( pEventsIf
, uno::UNO_QUERY
) );
457 xPlayerWindow
->addMouseListener( uno::Reference
< awt::XMouseListener
>( pEventsIf
, uno::UNO_QUERY
) );
458 xPlayerWindow
->addMouseMotionListener( uno::Reference
< awt::XMouseMotionListener
>( pEventsIf
, uno::UNO_QUERY
) );
459 xPlayerWindow
->addFocusListener( uno::Reference
< awt::XFocusListener
>( pEventsIf
, uno::UNO_QUERY
) );
463 mxPlayerWindow
.clear();
465 if( mxPlayerWindow
.is() )
466 mpChildWindow
->Show();
468 mpChildWindow
->Hide();
470 if( mpMediaWindowControl
)
474 updateMediaItem( aItem
);
475 mpMediaWindowControl
->setState( aItem
);
479 void MediaWindowImpl::setPosSize(const tools::Rectangle
& rRect
)
481 SetPosSizePixel(rRect
.TopLeft(), rRect
.GetSize());
484 void MediaWindowImpl::setPointer(PointerStyle aPointer
)
486 SetPointer(aPointer
);
489 mpChildWindow
->SetPointer(aPointer
);
491 if (mxPlayerWindow
.is())
497 case PointerStyle::Cross
:
498 nPointer
= awt::SystemPointer::CROSS
;
500 case PointerStyle::Hand
:
501 nPointer
= awt::SystemPointer::HAND
;
503 case PointerStyle::Move
:
504 nPointer
= awt::SystemPointer::MOVE
;
506 case PointerStyle::Wait
:
507 nPointer
= awt::SystemPointer::WAIT
;
510 nPointer
= awt::SystemPointer::ARROW
;
514 mxPlayerWindow
->setPointerType(nPointer
);
518 void MediaWindowImpl::Resize()
520 const Size
aCurSize(GetOutputSizePixel());
521 const sal_Int32
nOffset(mpMediaWindowControl
? AVMEDIA_CONTROLOFFSET
: 0);
523 Size
aPlayerWindowSize(aCurSize
.Width() - (nOffset
<< 1),
524 aCurSize
.Height() - (nOffset
<< 1));
526 if (mpMediaWindowControl
)
528 const sal_Int32 nControlHeight
= mpMediaWindowControl
->GetSizePixel().Height();
529 const sal_Int32 nControlY
= std::max(aCurSize
.Height() - nControlHeight
- nOffset
, 0L);
531 aPlayerWindowSize
.setHeight( nControlY
- (nOffset
<< 1) );
532 mpMediaWindowControl
->SetPosSizePixel(Point(nOffset
, nControlY
), Size(aCurSize
.Width() - (nOffset
<< 1), nControlHeight
));
535 mpChildWindow
->SetPosSizePixel(Point(0, 0), aPlayerWindowSize
);
537 if (mxPlayerWindow
.is())
538 mxPlayerWindow
->setPosSize(0, 0, aPlayerWindowSize
.Width(), aPlayerWindowSize
.Height(), 0);
541 void MediaWindowImpl::StateChanged(StateChangedType eType
)
543 if (mxPlayerWindow
.is())
545 // stop playing when going disabled or hidden
548 case StateChangedType::Visible
:
550 stopPlayingInternal(!IsVisible());
551 mxPlayerWindow
->setVisible(IsVisible());
555 case StateChangedType::Enable
:
557 stopPlayingInternal(!IsEnabled());
558 mxPlayerWindow
->setEnable(IsEnabled());
568 void MediaWindowImpl::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
570 if (mxPlayerWindow
.is())
571 mxPlayerWindow
->update();
573 BitmapEx
* pLogo
= nullptr;
578 mpEmptyBmpEx
.reset(new BitmapEx(AVMEDIA_BMP_EMPTYLOGO
));
580 pLogo
= mpEmptyBmpEx
.get();
582 else if (!mxPlayerWindow
.is())
585 mpAudioBmpEx
.reset(new BitmapEx(AVMEDIA_BMP_AUDIOLOGO
));
587 pLogo
= mpAudioBmpEx
.get();
593 const Point
aBasePos(mpChildWindow
->GetPosPixel());
594 const tools::Rectangle
aVideoRect(aBasePos
, mpChildWindow
->GetSizePixel());
596 if (pLogo
&& !pLogo
->IsEmpty() && (aVideoRect
.GetWidth() > 0) && (aVideoRect
.GetHeight() > 0))
598 Size
aLogoSize(pLogo
->GetSizePixel());
599 const Color
aBackgroundColor(67, 67, 67);
601 rRenderContext
.SetLineColor(aBackgroundColor
);
602 rRenderContext
.SetFillColor(aBackgroundColor
);
603 rRenderContext
.DrawRect(aVideoRect
);
605 if ((aLogoSize
.Width() > aVideoRect
.GetWidth() || aLogoSize
.Height() > aVideoRect
.GetHeight() ) &&
606 (aLogoSize
.Height() > 0))
608 const double fLogoWH
= double(aLogoSize
.Width()) / aLogoSize
.Height();
610 if (fLogoWH
< (double(aVideoRect
.GetWidth()) / aVideoRect
.GetHeight()))
612 aLogoSize
.setWidth( long(aVideoRect
.GetHeight() * fLogoWH
) );
613 aLogoSize
.setHeight( aVideoRect
.GetHeight() );
617 aLogoSize
.setWidth( aVideoRect
.GetWidth() );
618 aLogoSize
.setHeight( long(aVideoRect
.GetWidth() / fLogoWH
) );
622 Point
aPoint(aBasePos
.X() + ((aVideoRect
.GetWidth() - aLogoSize
.Width()) >> 1),
623 aBasePos
.Y() + ((aVideoRect
.GetHeight() - aLogoSize
.Height()) >> 1));
625 rRenderContext
.DrawBitmapEx(aPoint
, aLogoSize
, *pLogo
);
629 void MediaWindowImpl::GetFocus()
633 void MediaWindowImpl::MouseMove(const MouseEvent
& rMEvt
)
636 mpMediaWindow
->MouseMove(rMEvt
);
639 void MediaWindowImpl::MouseButtonDown(const MouseEvent
& rMEvt
)
642 mpMediaWindow
->MouseButtonDown(rMEvt
);
645 void MediaWindowImpl::MouseButtonUp(const MouseEvent
& rMEvt
)
648 mpMediaWindow
->MouseButtonUp(rMEvt
);
651 void MediaWindowImpl::KeyInput(const KeyEvent
& rKEvt
)
654 mpMediaWindow
->KeyInput(rKEvt
);
657 void MediaWindowImpl::KeyUp(const KeyEvent
& rKEvt
)
660 mpMediaWindow
->KeyUp(rKEvt
);
663 void MediaWindowImpl::Command(const CommandEvent
& rCEvt
)
666 mpMediaWindow
->Command(rCEvt
);
669 sal_Int8
MediaWindowImpl::AcceptDrop(const AcceptDropEvent
& rEvt
)
671 return (mpMediaWindow
? mpMediaWindow
->AcceptDrop(rEvt
) : 0);
674 sal_Int8
MediaWindowImpl::ExecuteDrop(const ExecuteDropEvent
& rEvt
)
676 return (mpMediaWindow
? mpMediaWindow
->ExecuteDrop(rEvt
) : 0);
679 void MediaWindowImpl::StartDrag(sal_Int8 nAction
, const Point
& rPosPixel
)
682 mpMediaWindow
->StartDrag(nAction
, rPosPixel
);
686 } // namespace avmedia
688 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */