nss: upgrade to release 3.73
[LibreOffice.git] / avmedia / source / viewer / mediawindow_impl.cxx
blobdec4d00a52f1902c74b644432e3f05e2305e0961
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <iostream>
21 #include "mediawindow_impl.hxx"
22 #include "mediaevent_impl.hxx"
23 #include <mediamisc.hxx>
24 #include <bitmaps.hlst>
25 #include <helpids.h>
27 #include <algorithm>
28 #include <string_view>
30 #include <sal/log.hxx>
31 #include <comphelper/processfactory.hxx>
32 #include <tools/diagnose_ex.h>
33 #include <tools/urlobj.hxx>
34 #include <unotools/securityoptions.hxx>
35 #include <vcl/bitmapex.hxx>
36 #include <vcl/svapp.hxx>
37 #include <vcl/sysdata.hxx>
38 #include <vcl/commandevent.hxx>
39 #include <vcl/event.hxx>
40 #include <vcl/ptrstyle.hxx>
42 #include <com/sun/star/awt/SystemPointer.hpp>
43 #include <com/sun/star/lang/XComponent.hpp>
44 #include <com/sun/star/media/XManager.hpp>
45 #include <com/sun/star/uno/XComponentContext.hpp>
46 using namespace ::com::sun::star;
48 namespace avmedia::priv {
50 MediaWindowControl::MediaWindowControl(vcl::Window* pParent)
51 : MediaControl(pParent, MediaControlStyle::MultiLine)
55 void MediaWindowControl::update()
57 MediaItem aItem;
59 static_cast< MediaWindowImpl* >( GetParent() )->updateMediaItem( aItem );
60 setState(aItem);
63 void MediaWindowControl::execute(const MediaItem& rItem)
65 static_cast<MediaWindowImpl*>(GetParent())->executeMediaItem(rItem);
68 MediaChildWindow::MediaChildWindow(vcl::Window* pParent)
69 : SystemChildWindow(pParent, WB_CLIPCHILDREN)
73 void MediaChildWindow::MouseMove( const MouseEvent& rMEvt )
75 const MouseEvent aTransformedEvent( GetParent()->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) ),
76 rMEvt.GetClicks(), rMEvt.GetMode(), rMEvt.GetButtons(), rMEvt.GetModifier() );
78 SystemChildWindow::MouseMove( rMEvt );
79 GetParent()->MouseMove( aTransformedEvent );
82 void MediaChildWindow::MouseButtonDown( const MouseEvent& rMEvt )
84 const MouseEvent aTransformedEvent( GetParent()->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) ),
85 rMEvt.GetClicks(), rMEvt.GetMode(), rMEvt.GetButtons(), rMEvt.GetModifier() );
87 SystemChildWindow::MouseButtonDown( rMEvt );
88 GetParent()->MouseButtonDown( aTransformedEvent );
91 void MediaChildWindow::MouseButtonUp( const MouseEvent& rMEvt )
93 const MouseEvent aTransformedEvent( GetParent()->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) ),
94 rMEvt.GetClicks(), rMEvt.GetMode(), rMEvt.GetButtons(), rMEvt.GetModifier() );
96 SystemChildWindow::MouseButtonUp( rMEvt );
97 GetParent()->MouseButtonUp( aTransformedEvent );
100 void MediaChildWindow::KeyInput( const KeyEvent& rKEvt )
102 SystemChildWindow::KeyInput( rKEvt );
103 GetParent()->KeyInput( rKEvt );
106 void MediaChildWindow::KeyUp( const KeyEvent& rKEvt )
108 SystemChildWindow::KeyUp( rKEvt );
109 GetParent()->KeyUp( rKEvt );
112 void MediaChildWindow::Command( const CommandEvent& rCEvt )
114 const CommandEvent aTransformedEvent( GetParent()->ScreenToOutputPixel( OutputToScreenPixel( rCEvt.GetMousePosPixel() ) ),
115 rCEvt.GetCommand(), rCEvt.IsMouseEvent(), rCEvt.GetEventData() );
117 SystemChildWindow::Command( rCEvt );
118 GetParent()->Command( aTransformedEvent );
121 MediaWindowImpl::MediaWindowImpl(vcl::Window* pParent, MediaWindow* pMediaWindow, bool bInternalMediaControl)
122 : Control(pParent)
123 , DropTargetHelper(this)
124 , DragSourceHelper(this)
125 , mpMediaWindow(pMediaWindow)
126 , mpMediaWindowControl(bInternalMediaControl ? VclPtr<MediaWindowControl>::Create(this) : nullptr)
128 if (mpMediaWindowControl)
130 mpMediaWindowControl->SetSizePixel(mpMediaWindowControl->GetOptimalSize());
131 mpMediaWindowControl->Show();
135 MediaWindowImpl::~MediaWindowImpl()
137 disposeOnce();
140 void MediaWindowImpl::dispose()
142 if (mxEvents.is())
143 mxEvents->cleanUp();
145 if (mxPlayerWindow.is())
147 auto pEventsIf = static_cast<cppu::OWeakObject*>(mxEvents.get());
148 mxPlayerWindow->removeKeyListener( uno::Reference< awt::XKeyListener >( pEventsIf, uno::UNO_QUERY ) );
149 mxPlayerWindow->removeMouseListener( uno::Reference< awt::XMouseListener >( pEventsIf, uno::UNO_QUERY ) );
150 mxPlayerWindow->removeMouseMotionListener( uno::Reference< awt::XMouseMotionListener >( pEventsIf, uno::UNO_QUERY ) );
151 mxPlayerWindow->dispose();
152 mxPlayerWindow.clear();
155 uno::Reference< lang::XComponent > xComponent( mxPlayer, uno::UNO_QUERY );
156 if (xComponent.is()) // this stops the player
157 xComponent->dispose();
159 mxPlayer.clear();
161 mpMediaWindow = nullptr;
163 mpEmptyBmpEx.reset();
164 mpAudioBmpEx.reset();
165 mpMediaWindowControl.disposeAndClear();
166 mpChildWindow.disposeAndClear();
168 Control::dispose();
171 uno::Reference<media::XPlayer> MediaWindowImpl::createPlayer(const OUString& rURL, const OUString& rReferer, const OUString* pMimeType)
173 uno::Reference<media::XPlayer> xPlayer;
175 if( rURL.isEmpty() )
176 return xPlayer;
178 if (SvtSecurityOptions().isUntrustedReferer(rReferer))
180 return xPlayer;
183 if (!pMimeType || *pMimeType == AVMEDIA_MIMETYPE_COMMON)
185 uno::Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext());
187 static std::u16string_view aServiceManagers[] =
189 u"" AVMEDIA_MANAGER_SERVICE_PREFERRED,
190 u"" AVMEDIA_MANAGER_SERVICE_NAME,
193 for (const auto& rServiceName : aServiceManagers)
195 xPlayer = createPlayer(rURL, rServiceName, xContext);
196 if (xPlayer)
197 break;
201 return xPlayer;
204 uno::Reference< media::XPlayer > MediaWindowImpl::createPlayer(
205 const OUString& rURL, const OUString& rManagerServName,
206 const uno::Reference< uno::XComponentContext >& xContext)
208 uno::Reference< media::XPlayer > xPlayer;
211 uno::Reference< media::XManager > xManager (
212 xContext->getServiceManager()->createInstanceWithContext(rManagerServName, xContext),
213 uno::UNO_QUERY );
214 if( xManager.is() )
215 xPlayer = xManager->createPlayer( rURL );
216 else
217 SAL_INFO( "avmedia", "failed to create media player service " << rManagerServName );
218 } catch ( const uno::Exception & )
220 TOOLS_WARN_EXCEPTION( "avmedia", "couldn't create media player " << rManagerServName);
222 return xPlayer;
225 void MediaWindowImpl::setURL( const OUString& rURL,
226 OUString const& rTempURL, OUString const& rReferer)
228 maReferer = rReferer;
229 if( rURL == getURL() )
230 return;
232 if( mxPlayer.is() )
233 mxPlayer->stop();
235 if( mxPlayerWindow.is() )
237 mxPlayerWindow->setVisible( false );
238 mxPlayerWindow.clear();
241 mxPlayer.clear();
242 mTempFileURL.clear();
244 if (!rTempURL.isEmpty())
246 maFileURL = rURL;
247 mTempFileURL = rTempURL;
249 else
251 INetURLObject aURL( rURL );
253 if (aURL.GetProtocol() != INetProtocol::NotValid)
254 maFileURL = aURL.GetMainURL(INetURLObject::DecodeMechanism::Unambiguous);
255 else
256 maFileURL = rURL;
259 mxPlayer = createPlayer((!mTempFileURL.isEmpty()) ? mTempFileURL : maFileURL, rReferer, &m_sMimeType );
260 onURLChanged();
263 const OUString& MediaWindowImpl::getURL() const
265 return maFileURL;
268 bool MediaWindowImpl::isValid() const
270 return mxPlayer.is();
273 Size MediaWindowImpl::getPreferredSize() const
275 Size aRet(480, 360);
277 if( mxPlayer.is() )
279 awt::Size aPrefSize( mxPlayer->getPreferredPlayerWindowSize() );
281 aRet.setWidth( aPrefSize.Width );
282 aRet.setHeight( aPrefSize.Height );
285 return aRet;
288 bool MediaWindowImpl::start()
290 return mxPlayer.is() && ( mxPlayer->start(), true );
293 void MediaWindowImpl::updateMediaItem( MediaItem& rItem ) const
295 if( isPlaying() )
296 rItem.setState( MediaState::Play );
297 else
298 rItem.setState( ( getMediaTime() == 0.0 ) ? MediaState::Stop : MediaState::Pause );
300 rItem.setDuration( getDuration() );
301 rItem.setTime( getMediaTime() );
302 rItem.setLoop( mxPlayer.is() && mxPlayer->isPlaybackLoop() );
303 rItem.setMute( mxPlayer.is() && mxPlayer->isMute() );
304 rItem.setVolumeDB( mxPlayer.is() ? mxPlayer->getVolumeDB() : 0 );
305 rItem.setZoom( mxPlayerWindow.is() ? mxPlayerWindow->getZoomLevel() : media::ZoomLevel_NOT_AVAILABLE );
306 rItem.setURL( getURL(), mTempFileURL, maReferer );
309 void MediaWindowImpl::executeMediaItem( const MediaItem& rItem )
311 const AVMediaSetMask nMaskSet = rItem.getMaskSet();
313 // set URL first
314 if (nMaskSet & AVMediaSetMask::URL)
316 m_sMimeType = rItem.getMimeType();
317 setURL(rItem.getURL(), rItem.getTempURL(), rItem.getReferer());
320 // set different states next
321 if (nMaskSet & AVMediaSetMask::TIME)
322 setMediaTime(std::min(rItem.getTime(), getDuration()));
324 if (nMaskSet & AVMediaSetMask::LOOP && mxPlayer.is() )
325 mxPlayer->setPlaybackLoop( rItem.isLoop() );
327 if (nMaskSet & AVMediaSetMask::MUTE && mxPlayer.is() )
328 mxPlayer->setMute( rItem.isMute() );
330 if (nMaskSet & AVMediaSetMask::VOLUMEDB && mxPlayer.is() )
331 mxPlayer->setVolumeDB( rItem.getVolumeDB() );
333 if (nMaskSet & AVMediaSetMask::ZOOM && mxPlayerWindow.is() )
334 mxPlayerWindow->setZoomLevel( rItem.getZoom() );
336 // set play state at last
337 if (!(nMaskSet & AVMediaSetMask::STATE))
338 return;
340 switch (rItem.getState())
342 case MediaState::Play:
344 if (!isPlaying())
345 start();
347 break;
349 case MediaState::Pause:
351 if (isPlaying())
352 stop();
354 break;
356 case MediaState::Stop:
358 if (isPlaying())
360 setMediaTime( 0.0 );
361 stop();
362 setMediaTime( 0.0 );
365 break;
369 void MediaWindowImpl::stop()
371 if( mxPlayer.is() )
372 mxPlayer->stop();
375 bool MediaWindowImpl::isPlaying() const
377 return( mxPlayer.is() && mxPlayer->isPlaying() );
380 double MediaWindowImpl::getDuration() const
382 return( mxPlayer.is() ? mxPlayer->getDuration() : 0.0 );
385 void MediaWindowImpl::setMediaTime( double fTime )
387 if( mxPlayer.is() )
388 mxPlayer->setMediaTime( fTime );
391 double MediaWindowImpl::getMediaTime() const
393 return( mxPlayer.is() ? mxPlayer->getMediaTime() : 0.0 );
396 void MediaWindowImpl::stopPlayingInternal(bool bStop)
398 if (isPlaying())
400 bStop ? mxPlayer->stop() : mxPlayer->start();
404 void MediaWindowImpl::onURLChanged()
406 if (m_sMimeType == AVMEDIA_MIMETYPE_COMMON)
408 mpChildWindow.disposeAndClear();
409 mpChildWindow.reset(VclPtr<MediaChildWindow>::Create(this));
411 if (!mpChildWindow)
412 return;
413 mpChildWindow->SetHelpId(HID_AVMEDIA_PLAYERWINDOW);
414 mxEvents = new MediaEventListenersImpl(*mpChildWindow);
416 if (mxPlayer.is())
418 Resize();
419 uno::Sequence<uno::Any> aArgs( 3 );
420 uno::Reference<media::XPlayerWindow> xPlayerWindow;
421 const Point aPoint;
422 const Size aSize(mpChildWindow->GetSizePixel());
424 sal_IntPtr nParentWindowHandle(0);
425 const SystemEnvData* pEnvData = mpChildWindow->GetSystemData();
426 // tdf#139609 gtk doesn't need the handle, and fetching it is undesirable
427 if (!pEnvData || pEnvData->toolkit != SystemEnvData::Toolkit::Gtk3)
428 nParentWindowHandle = mpChildWindow->GetParentWindowHandle();
429 aArgs[0] <<= nParentWindowHandle;
430 aArgs[1] <<= awt::Rectangle(aPoint.X(), aPoint.Y(), aSize.Width(), aSize.Height());
431 aArgs[2] <<= reinterpret_cast<sal_IntPtr>(mpChildWindow.get());
435 xPlayerWindow = mxPlayer->createPlayerWindow( aArgs );
437 catch( const uno::RuntimeException& )
439 // happens eg, on MacOSX where Java frames cannot be created from X11 window handles
442 mxPlayerWindow = xPlayerWindow;
444 if( xPlayerWindow.is() )
446 auto pEventsIf = static_cast<cppu::OWeakObject*>(mxEvents.get());
447 xPlayerWindow->addKeyListener( uno::Reference< awt::XKeyListener >( pEventsIf, uno::UNO_QUERY ) );
448 xPlayerWindow->addMouseListener( uno::Reference< awt::XMouseListener >( pEventsIf, uno::UNO_QUERY ) );
449 xPlayerWindow->addMouseMotionListener( uno::Reference< awt::XMouseMotionListener >( pEventsIf, uno::UNO_QUERY ) );
450 xPlayerWindow->addFocusListener( uno::Reference< awt::XFocusListener >( pEventsIf, uno::UNO_QUERY ) );
453 else
454 mxPlayerWindow.clear();
456 if( mxPlayerWindow.is() )
457 mpChildWindow->Show();
458 else
459 mpChildWindow->Hide();
461 if( mpMediaWindowControl )
463 MediaItem aItem;
465 updateMediaItem( aItem );
466 mpMediaWindowControl->setState( aItem );
470 void MediaWindowImpl::setPosSize(const tools::Rectangle& rRect)
472 SetPosSizePixel(rRect.TopLeft(), rRect.GetSize());
475 void MediaWindowImpl::setPointer(PointerStyle aPointer)
477 SetPointer(aPointer);
479 if (mpChildWindow)
480 mpChildWindow->SetPointer(aPointer);
482 if (!mxPlayerWindow.is())
483 return;
485 sal_Int32 nPointer;
487 switch (aPointer)
489 case PointerStyle::Cross:
490 nPointer = awt::SystemPointer::CROSS;
491 break;
492 case PointerStyle::Hand:
493 nPointer = awt::SystemPointer::HAND;
494 break;
495 case PointerStyle::Move:
496 nPointer = awt::SystemPointer::MOVE;
497 break;
498 case PointerStyle::Wait:
499 nPointer = awt::SystemPointer::WAIT;
500 break;
501 default:
502 nPointer = awt::SystemPointer::ARROW;
503 break;
506 mxPlayerWindow->setPointerType(nPointer);
509 void MediaWindowImpl::Resize()
511 const Size aCurSize(GetOutputSizePixel());
512 const sal_Int32 nOffset(mpMediaWindowControl ? AVMEDIA_CONTROLOFFSET : 0);
514 Size aPlayerWindowSize(aCurSize.Width() - (nOffset << 1),
515 aCurSize.Height() - (nOffset << 1));
517 if (mpMediaWindowControl)
519 const sal_Int32 nControlHeight = mpMediaWindowControl->GetSizePixel().Height();
520 const sal_Int32 nControlY = std::max(aCurSize.Height() - nControlHeight - nOffset, tools::Long(0));
522 aPlayerWindowSize.setHeight( nControlY - (nOffset << 1) );
523 mpMediaWindowControl->SetPosSizePixel(Point(nOffset, nControlY ), Size(aCurSize.Width() - (nOffset << 1), nControlHeight));
525 if (mpChildWindow)
526 mpChildWindow->SetPosSizePixel(Point(0, 0), aPlayerWindowSize);
528 if (mxPlayerWindow.is())
529 mxPlayerWindow->setPosSize(0, 0, aPlayerWindowSize.Width(), aPlayerWindowSize.Height(), 0);
532 void MediaWindowImpl::StateChanged(StateChangedType eType)
534 if (!mxPlayerWindow.is())
535 return;
537 // stop playing when going disabled or hidden
538 switch (eType)
540 case StateChangedType::Visible:
542 stopPlayingInternal(!IsVisible());
543 mxPlayerWindow->setVisible(IsVisible());
545 break;
547 case StateChangedType::Enable:
549 stopPlayingInternal(!IsEnabled());
550 mxPlayerWindow->setEnable(IsEnabled());
552 break;
554 default:
555 break;
559 void MediaWindowImpl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
561 if (mxPlayerWindow.is())
562 mxPlayerWindow->update();
564 BitmapEx* pLogo = nullptr;
566 if (!mxPlayer.is())
568 if (!mpEmptyBmpEx)
569 mpEmptyBmpEx.reset(new BitmapEx(AVMEDIA_BMP_EMPTYLOGO));
571 pLogo = mpEmptyBmpEx.get();
573 else if (!mxPlayerWindow.is())
575 if (!mpAudioBmpEx)
576 mpAudioBmpEx.reset(new BitmapEx(AVMEDIA_BMP_AUDIOLOGO));
578 pLogo = mpAudioBmpEx.get();
581 if (!mpChildWindow)
582 return;
584 const Point aBasePos(mpChildWindow->GetPosPixel());
585 const tools::Rectangle aVideoRect(aBasePos, mpChildWindow->GetSizePixel());
587 if (!pLogo || pLogo->IsEmpty() || aVideoRect.IsEmpty())
588 return;
590 Size aLogoSize(pLogo->GetSizePixel());
591 const Color aBackgroundColor(67, 67, 67);
593 rRenderContext.SetLineColor(aBackgroundColor);
594 rRenderContext.SetFillColor(aBackgroundColor);
595 rRenderContext.DrawRect(aVideoRect);
597 if ((aLogoSize.Width() > aVideoRect.GetWidth() || aLogoSize.Height() > aVideoRect.GetHeight() ) &&
598 (aLogoSize.Height() > 0))
600 const double fLogoWH = double(aLogoSize.Width()) / aLogoSize.Height();
602 if (fLogoWH < (double(aVideoRect.GetWidth()) / aVideoRect.GetHeight()))
604 aLogoSize.setWidth( tools::Long(aVideoRect.GetHeight() * fLogoWH) );
605 aLogoSize.setHeight( aVideoRect.GetHeight() );
607 else
609 aLogoSize.setWidth( aVideoRect.GetWidth() );
610 aLogoSize.setHeight( tools::Long(aVideoRect.GetWidth() / fLogoWH) );
614 Point aPoint(aBasePos.X() + ((aVideoRect.GetWidth() - aLogoSize.Width()) >> 1),
615 aBasePos.Y() + ((aVideoRect.GetHeight() - aLogoSize.Height()) >> 1));
617 rRenderContext.DrawBitmapEx(aPoint, aLogoSize, *pLogo);
620 void MediaWindowImpl::GetFocus()
624 void MediaWindowImpl::MouseMove(const MouseEvent& rMEvt)
626 if (mpMediaWindow)
627 mpMediaWindow->MouseMove(rMEvt);
630 void MediaWindowImpl::MouseButtonDown(const MouseEvent& rMEvt)
632 if (mpMediaWindow)
633 mpMediaWindow->MouseButtonDown(rMEvt);
636 void MediaWindowImpl::MouseButtonUp(const MouseEvent& rMEvt)
638 if (mpMediaWindow)
639 mpMediaWindow->MouseButtonUp(rMEvt);
642 void MediaWindowImpl::KeyInput(const KeyEvent& rKEvt)
644 if (mpMediaWindow)
645 mpMediaWindow->KeyInput(rKEvt);
648 void MediaWindowImpl::KeyUp(const KeyEvent& rKEvt)
650 if (mpMediaWindow)
651 mpMediaWindow->KeyUp(rKEvt);
654 void MediaWindowImpl::Command(const CommandEvent& rCEvt)
656 if (mpMediaWindow)
657 mpMediaWindow->Command(rCEvt);
660 sal_Int8 MediaWindowImpl::AcceptDrop(const AcceptDropEvent& rEvt)
662 return (mpMediaWindow ? mpMediaWindow->AcceptDrop(rEvt) : 0);
665 sal_Int8 MediaWindowImpl::ExecuteDrop(const ExecuteDropEvent& rEvt)
667 return (mpMediaWindow ? mpMediaWindow->ExecuteDrop(rEvt) : 0);
670 void MediaWindowImpl::StartDrag(sal_Int8 nAction, const Point& rPosPixel)
672 if (mpMediaWindow)
673 mpMediaWindow->StartDrag(nAction, rPosPixel);
676 } // namespace
678 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */