tdf#145735 avmedia qt: Use QtMultimedia for Qt 6 media playback
Similar to the way that GTK 4's native facilities for video playback are used for the gtk4 VCL plugin, initially added in commit commitd0a527ec09
Author: Caolán McNamara <caolanm@redhat.com> Date: Thu Feb 10 12:55:18 2022 +0000 first cut at using Gtk4 built in video playback , implement media playback using QtMultimedia for the Qt 6 based VCL plugins (qt6/kf6) via a new service "com.sun.star.comp.avmedia.Manager_Qt". Video playback with the mechanism used for qt5 no longer works with qt6, as "qwidget5videosink" that gets used on Wayland for qt5 wasn't ported to Qt 6 and is unmaintained, s. the commit message of commit88d57cf241
Author: Michael Weghorn <m.weghorn@posteo.de> Date: Wed Sep 29 11:09:51 2021 +0200 qt6: Add a qt6 VCL plugin for more details. Additionally, this also doesn't work properly any more on X11/with the xcb Qt QPA platform, see tdf#145735 comment 7. Instead of using GStreamer directly, let Qt handle the low-level stuff by using the QtMultimedia module [1] instead. This adds a new dependency on QtMultimedia. For building, this requires installing the Qt 6 QtMultimedia development headers (e.g. package `qt6-multimedia-dev` on current Debian testing). Except for WASM, the use of QtMultimedia is enabled by default when building with autogen options `--enable-qt6` or `--enable-kf6`, but can explicitly be disabled using `--disable-qt6-multimedia`. In tests with the qt6 VCL plugin on Debian testing, with a sample presentation containing an embedded video, attachment 145517 from tdf#120452, video playback generally works for both, the xcb and the wayland Qt QPA platforms: * Video and audio are played as expected on the external screen in presentation mode when using the presenter console * Video and audio playback work in non-presentation mode by clicking on the video and using the controls in the Impress sidebar (play, pause,...). However, the following issues were observed with the current implementation: * There's an odd frame/margin around the video. * In non-presentation mode, the placeholder shown until the video gets started using the controls in the sidebar is just an "audio icon", not a frame from the actual video. (This might be related to the fact that `QtPlayer::createFrameGrabber` currently returns an empty reference.) * At least on Wayland (issue not observed with QT_QPA_PLATFORM=xcb so far), when using the presenter console, video playback in the presenter console (i.e. on the non-presentation screen) is unreliable: The video sometimes shows, but sometimes doesn't. At least the (more important) one on the presentation screen was reliably shown in my tests, however. Tested with git dev versions of qtbase (as of commit 8d5e7d50d8dbf1ad79bd8ff9f6ef6028eba481c9), qtwayland (as of commit 6f0ebd916f176f6fbe35af28caeb52b62768ac94) and qtmultimedia (as of commit 264b7e8d7d5683252102b5e5149685c8b8a70c2d). [1] https://doc.qt.io/qt-6/qtmultimedia-index.html Change-Id: I29c3c7ded01c61b49b192fa5c313d8a92c942185 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167869 Reviewed-by: Michael Weghorn <m.weghorn@posteo.de> Tested-by: Jenkins
This commit is contained in:
parent
4316851ec8
commit
441d8ed9be
15 changed files with 641 additions and 1 deletions
|
@ -656,6 +656,7 @@ $(eval $(call gb_Helper_register_libraries_for_install,PLAINLIBS_OOO,ooo, \
|
|||
$(call gb_Helper_optional,AVMEDIA, \
|
||||
$(if $(ENABLE_GSTREAMER_1_0),avmediagst) \
|
||||
$(if $(ENABLE_GTK4),avmediagtk) \
|
||||
$(if $(ENABLE_QT6_MULTIMEDIA),avmediaqt6) \
|
||||
$(if $(filter WNT,$(OS)),avmediawin) \
|
||||
) \
|
||||
cached1 \
|
||||
|
|
24
avmedia/CustomTarget_avmediaqt6_moc.mk
Normal file
24
avmedia/CustomTarget_avmediaqt6_moc.mk
Normal file
|
@ -0,0 +1,24 @@
|
|||
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
|
||||
#
|
||||
# This file is part of the LibreOffice project.
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
|
||||
$(eval $(call gb_CustomTarget_CustomTarget,avmedia/source/qt6))
|
||||
|
||||
$(call gb_CustomTarget_get_target,avmedia/source/qt6) : \
|
||||
$(gb_CustomTarget_workdir)/avmedia/source/qt6/QtPlayer.moc
|
||||
|
||||
|
||||
$(gb_CustomTarget_workdir)/avmedia/source/qt6/%.moc : \
|
||||
$(SRCDIR)/avmedia/source/qt6/%.hxx \
|
||||
| $(gb_CustomTarget_workdir)/avmedia/source/qt6/.dir
|
||||
$(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),$(true),MOC,1)
|
||||
$(call gb_Trace_StartRange,$(subst $(WORKDIR)/,,$@),MOC)
|
||||
$(MOC6) $< -o $@
|
||||
$(call gb_Trace_EndRange,$(subst $(WORKDIR)/,,$@),MOC)
|
||||
|
||||
# vim: set noet sw=4:
|
44
avmedia/Library_avmediaqt6.mk
Normal file
44
avmedia/Library_avmediaqt6.mk
Normal file
|
@ -0,0 +1,44 @@
|
|||
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
|
||||
#
|
||||
# This file is part of the LibreOffice project.
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
|
||||
$(eval $(call gb_Library_Library,avmediaqt6))
|
||||
|
||||
$(eval $(call gb_Library_set_componentfile,avmediaqt6,avmedia/source/qt6/avmediaqt,services))
|
||||
|
||||
$(eval $(call gb_Library_use_custom_headers,avmediaqt6,avmedia/source/qt6))
|
||||
|
||||
$(eval $(call gb_Library_set_include,avmediaqt6,\
|
||||
$$(INCLUDE) \
|
||||
-I$(SRCDIR)/avmedia/source/inc \
|
||||
-I$(SRCDIR)/avmedia/source/gstreamer \
|
||||
))
|
||||
|
||||
$(eval $(call gb_Library_use_externals,avmediaqt6,\
|
||||
qt6 \
|
||||
))
|
||||
|
||||
$(eval $(call gb_Library_use_sdk_api,avmediaqt6))
|
||||
|
||||
$(eval $(call gb_Library_use_libraries,avmediaqt6,\
|
||||
comphelper \
|
||||
cppu \
|
||||
cppuhelper \
|
||||
sal \
|
||||
salhelper \
|
||||
tl \
|
||||
vcl \
|
||||
))
|
||||
|
||||
$(eval $(call gb_Library_add_exception_objects,avmediaqt6,\
|
||||
avmedia/source/qt6/gstwindow \
|
||||
avmedia/source/qt6/QtManager \
|
||||
avmedia/source/qt6/QtPlayer \
|
||||
))
|
||||
|
||||
# vim: set noet sw=4 ts=4:
|
|
@ -31,6 +31,13 @@ $(eval $(call gb_Module_add_targets,avmedia,\
|
|||
))
|
||||
endif
|
||||
|
||||
ifneq ($(ENABLE_QT6_MULTIMEDIA),)
|
||||
$(eval $(call gb_Module_add_targets,avmedia,\
|
||||
CustomTarget_avmediaqt6_moc \
|
||||
Library_avmediaqt6 \
|
||||
))
|
||||
endif
|
||||
|
||||
ifeq ($(OS),MACOSX)
|
||||
$(eval $(call gb_Module_add_targets,avmedia,\
|
||||
Library_avmediaMacAVF \
|
||||
|
|
62
avmedia/source/qt6/QtManager.cxx
Normal file
62
avmedia/source/qt6/QtManager.cxx
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <com/sun/star/uno/XComponentContext.hpp>
|
||||
#include <cppuhelper/supportsservice.hxx>
|
||||
#include <rtl/ref.hxx>
|
||||
#include <tools/urlobj.hxx>
|
||||
|
||||
#include "QtManager.hxx"
|
||||
#include "QtPlayer.hxx"
|
||||
|
||||
namespace avmedia::qt
|
||||
{
|
||||
QtManager::QtManager() {}
|
||||
|
||||
QtManager::~QtManager() {}
|
||||
|
||||
css::uno::Reference<css::media::XPlayer> SAL_CALL QtManager::createPlayer(const OUString& rURL)
|
||||
{
|
||||
const INetURLObject aURL(rURL);
|
||||
OUString sMainURL = aURL.GetMainURL(INetURLObject::DecodeMechanism::Unambiguous);
|
||||
|
||||
rtl::Reference<QtPlayer> xPlayer(new QtPlayer);
|
||||
if (!xPlayer->create(sMainURL))
|
||||
{
|
||||
xPlayer->dispose();
|
||||
xPlayer.clear();
|
||||
}
|
||||
return xPlayer;
|
||||
}
|
||||
|
||||
OUString SAL_CALL QtManager::getImplementationName()
|
||||
{
|
||||
return u"com.sun.star.comp.media.Manager_Qt"_ustr;
|
||||
}
|
||||
|
||||
sal_Bool SAL_CALL QtManager::supportsService(const OUString& ServiceName)
|
||||
{
|
||||
return cppu::supportsService(this, ServiceName);
|
||||
}
|
||||
|
||||
css::uno::Sequence<OUString> SAL_CALL QtManager::getSupportedServiceNames()
|
||||
{
|
||||
return { u"com.sun.star.media.Manager"_ustr };
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
|
||||
com_sun_star_comp_media_Manager_Qt_get_implementation(css::uno::XComponentContext*,
|
||||
css::uno::Sequence<css::uno::Any> const&)
|
||||
{
|
||||
return cppu::acquire(new avmedia::qt::QtManager());
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
33
avmedia/source/qt6/QtManager.hxx
Normal file
33
avmedia/source/qt6/QtManager.hxx
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <com/sun/star/lang/XServiceInfo.hpp>
|
||||
#include <com/sun/star/media/XManager.hpp>
|
||||
#include <cppuhelper/implbase.hxx>
|
||||
|
||||
namespace avmedia::qt
|
||||
{
|
||||
class QtManager : public cppu::WeakImplHelper<css::media::XManager, css::lang::XServiceInfo>
|
||||
{
|
||||
public:
|
||||
explicit QtManager();
|
||||
virtual ~QtManager() override;
|
||||
|
||||
virtual css::uno::Reference<css::media::XPlayer>
|
||||
SAL_CALL createPlayer(const OUString& aURL) override;
|
||||
|
||||
virtual OUString SAL_CALL getImplementationName() override;
|
||||
virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
|
||||
virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
|
||||
};
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
328
avmedia/source/qt6/QtPlayer.cxx
Normal file
328
avmedia/source/qt6/QtPlayer.cxx
Normal file
|
@ -0,0 +1,328 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <sal/config.h>
|
||||
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtMultimedia/QAudioOutput>
|
||||
#include <QtMultimediaWidgets/QVideoWidget>
|
||||
#include <QtWidgets/QLayout>
|
||||
|
||||
#include <cppuhelper/supportsservice.hxx>
|
||||
#include <sal/log.hxx>
|
||||
#include <rtl/string.hxx>
|
||||
#include <tools/link.hxx>
|
||||
#include <vcl/BitmapTools.hxx>
|
||||
#include <vcl/graph.hxx>
|
||||
#include <vcl/svapp.hxx>
|
||||
#include <vcl/syschild.hxx>
|
||||
#include <vcl/sysdata.hxx>
|
||||
#include <vcl/timer.hxx>
|
||||
|
||||
#include <gstwindow.hxx>
|
||||
#include "QtPlayer.hxx"
|
||||
|
||||
#include <QtPlayer.moc>
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace
|
||||
{
|
||||
inline QString toQString(const OUString& rStr)
|
||||
{
|
||||
return QString::fromUtf16(rStr.getStr(), rStr.getLength());
|
||||
}
|
||||
}
|
||||
|
||||
namespace avmedia::qt
|
||||
{
|
||||
QtPlayer::QtPlayer()
|
||||
: QtPlayer_BASE(m_aMutex)
|
||||
, m_lListener(m_aMutex)
|
||||
{
|
||||
}
|
||||
|
||||
bool QtPlayer::create(const OUString& rURL)
|
||||
{
|
||||
const QUrl aQUrl(toQString(rURL));
|
||||
if (!aQUrl.isValid() || !aQUrl.isLocalFile())
|
||||
return false;
|
||||
|
||||
m_xMediaPlayer = std::make_unique<QMediaPlayer>();
|
||||
m_xMediaPlayer->setSource(aQUrl);
|
||||
QAudioOutput* pAudioOutput = new QAudioOutput;
|
||||
pAudioOutput->setVolume(50);
|
||||
m_xMediaPlayer->setAudioOutput(pAudioOutput);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SAL_CALL QtPlayer::start()
|
||||
{
|
||||
osl::MutexGuard aGuard(m_aMutex);
|
||||
|
||||
assert(m_xMediaPlayer);
|
||||
m_xMediaPlayer->play();
|
||||
}
|
||||
|
||||
void SAL_CALL QtPlayer::stop()
|
||||
{
|
||||
osl::MutexGuard aGuard(m_aMutex);
|
||||
|
||||
assert(m_xMediaPlayer);
|
||||
// don't use QMediaPlayer::stop because XPlayer::stop should leave the position unchanged
|
||||
m_xMediaPlayer->pause();
|
||||
}
|
||||
|
||||
sal_Bool SAL_CALL QtPlayer::isPlaying()
|
||||
{
|
||||
osl::MutexGuard aGuard(m_aMutex);
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
|
||||
assert(m_xMediaPlayer);
|
||||
return m_xMediaPlayer->isPlaying();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
double SAL_CALL QtPlayer::getDuration()
|
||||
{
|
||||
osl::MutexGuard aGuard(m_aMutex);
|
||||
|
||||
assert(m_xMediaPlayer);
|
||||
return m_xMediaPlayer->duration() / 1000.0;
|
||||
}
|
||||
|
||||
void SAL_CALL QtPlayer::setMediaTime(double fTime)
|
||||
{
|
||||
osl::MutexGuard aGuard(m_aMutex);
|
||||
|
||||
assert(m_xMediaPlayer);
|
||||
m_xMediaPlayer->setPosition(fTime * 1000);
|
||||
}
|
||||
|
||||
double SAL_CALL QtPlayer::getMediaTime()
|
||||
{
|
||||
osl::MutexGuard aGuard(m_aMutex);
|
||||
|
||||
assert(m_xMediaPlayer);
|
||||
return m_xMediaPlayer->position() / 1000.0;
|
||||
}
|
||||
|
||||
void SAL_CALL QtPlayer::setPlaybackLoop(sal_Bool bSet)
|
||||
{
|
||||
assert(m_xMediaPlayer);
|
||||
const int nLoops = bSet ? QMediaPlayer::Infinite : QMediaPlayer::Once;
|
||||
m_xMediaPlayer->setLoops(nLoops);
|
||||
}
|
||||
|
||||
sal_Bool SAL_CALL QtPlayer::isPlaybackLoop()
|
||||
{
|
||||
assert(m_xMediaPlayer);
|
||||
return m_xMediaPlayer->loops() == QMediaPlayer::Infinite;
|
||||
}
|
||||
|
||||
void SAL_CALL QtPlayer::setVolumeDB(sal_Int16 nVolumeDB)
|
||||
{
|
||||
osl::MutexGuard aGuard(m_aMutex);
|
||||
|
||||
// range is -40 for silence to 0 for full volume
|
||||
const sal_Int16 nVolume = std::clamp<sal_Int16>(nVolumeDB, -40, 0);
|
||||
double fValue = (nVolume + 40) / 40.0;
|
||||
assert(m_xMediaPlayer);
|
||||
QAudioOutput* pAudioOutput = m_xMediaPlayer->audioOutput();
|
||||
assert(pAudioOutput);
|
||||
pAudioOutput->setVolume(fValue);
|
||||
}
|
||||
|
||||
sal_Int16 SAL_CALL QtPlayer::getVolumeDB()
|
||||
{
|
||||
osl::MutexGuard aGuard(m_aMutex);
|
||||
|
||||
assert(m_xMediaPlayer);
|
||||
QAudioOutput* pAudioOutput = m_xMediaPlayer->audioOutput();
|
||||
assert(pAudioOutput);
|
||||
|
||||
double fVolume = pAudioOutput->volume();
|
||||
return (fVolume * 40) - 40;
|
||||
}
|
||||
|
||||
void SAL_CALL QtPlayer::setMute(sal_Bool bSet)
|
||||
{
|
||||
osl::MutexGuard aGuard(m_aMutex);
|
||||
|
||||
assert(m_xMediaPlayer);
|
||||
QAudioOutput* pAudioOutput = m_xMediaPlayer->audioOutput();
|
||||
assert(pAudioOutput);
|
||||
pAudioOutput->setMuted(bSet);
|
||||
}
|
||||
|
||||
sal_Bool SAL_CALL QtPlayer::isMute()
|
||||
{
|
||||
osl::MutexGuard aGuard(m_aMutex);
|
||||
|
||||
assert(m_xMediaPlayer);
|
||||
QAudioOutput* pAudioOutput = m_xMediaPlayer->audioOutput();
|
||||
assert(pAudioOutput);
|
||||
return pAudioOutput->isMuted();
|
||||
}
|
||||
|
||||
awt::Size SAL_CALL QtPlayer::getPreferredPlayerWindowSize()
|
||||
{
|
||||
osl::MutexGuard aGuard(m_aMutex);
|
||||
|
||||
awt::Size aSize(0, 0);
|
||||
return aSize;
|
||||
}
|
||||
|
||||
uno::Reference<::media::XPlayerWindow>
|
||||
SAL_CALL QtPlayer::createPlayerWindow(const uno::Sequence<uno::Any>& rArguments)
|
||||
{
|
||||
osl::MutexGuard aGuard(m_aMutex);
|
||||
|
||||
if (rArguments.getLength() <= 2)
|
||||
{
|
||||
uno::Reference<::media::XPlayerWindow> xRet = new ::avmedia::gstreamer::Window;
|
||||
return xRet;
|
||||
}
|
||||
|
||||
sal_IntPtr pIntPtr = 0;
|
||||
rArguments[2] >>= pIntPtr;
|
||||
SystemChildWindow* pParentWindow = reinterpret_cast<SystemChildWindow*>(pIntPtr);
|
||||
if (!pParentWindow)
|
||||
return nullptr;
|
||||
|
||||
const SystemEnvData* pParentEnvData = pParentWindow->GetSystemData();
|
||||
if (!pParentEnvData)
|
||||
return nullptr;
|
||||
|
||||
QWidget* pParent = static_cast<QWidget*>(pParentEnvData->pWidget);
|
||||
QVideoWidget* pVideoWidget = new QVideoWidget(pParent);
|
||||
pVideoWidget->setAspectRatioMode(Qt::IgnoreAspectRatio);
|
||||
pVideoWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
|
||||
assert(!m_xMediaPlayer->videoOutput() && "Video widget already set.");
|
||||
m_xMediaPlayer->setVideoOutput(pVideoWidget);
|
||||
|
||||
// retrieve the layout (which is set in the QtObjectWidget ctor)
|
||||
QLayout* pLayout = pParent->layout();
|
||||
assert(pLayout);
|
||||
pLayout->addWidget(pVideoWidget);
|
||||
|
||||
uno::Reference<::media::XPlayerWindow> xRet = new ::avmedia::gstreamer::Window;
|
||||
return xRet;
|
||||
}
|
||||
|
||||
uno::Reference<media::XFrameGrabber> SAL_CALL QtPlayer::createFrameGrabber() { return nullptr; }
|
||||
|
||||
void SAL_CALL
|
||||
QtPlayer::addPlayerListener(const css::uno::Reference<css::media::XPlayerListener>& rListener)
|
||||
{
|
||||
m_lListener.addInterface(cppu::UnoType<css::media::XPlayerListener>::get(), rListener);
|
||||
if (isReadyToPlay())
|
||||
{
|
||||
css::lang::EventObject aEvent;
|
||||
aEvent.Source = getXWeak();
|
||||
rListener->preferredPlayerWindowSizeAvailable(aEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
installNotify();
|
||||
}
|
||||
}
|
||||
|
||||
void SAL_CALL
|
||||
QtPlayer::removePlayerListener(const css::uno::Reference<css::media::XPlayerListener>& rListener)
|
||||
{
|
||||
m_lListener.removeInterface(cppu::UnoType<css::media::XPlayerListener>::get(), rListener);
|
||||
}
|
||||
|
||||
OUString SAL_CALL QtPlayer::getImplementationName()
|
||||
{
|
||||
return u"com.sun.star.comp.avmedia.Player_Qt"_ustr;
|
||||
}
|
||||
|
||||
sal_Bool SAL_CALL QtPlayer::supportsService(const OUString& rServiceName)
|
||||
{
|
||||
return cppu::supportsService(this, rServiceName);
|
||||
}
|
||||
|
||||
uno::Sequence<OUString> SAL_CALL QtPlayer::getSupportedServiceNames()
|
||||
{
|
||||
return { u"com.sun.star.media.Player_Qt"_ustr };
|
||||
}
|
||||
|
||||
void SAL_CALL QtPlayer::disposing()
|
||||
{
|
||||
osl::MutexGuard aGuard(m_aMutex);
|
||||
stop();
|
||||
QtPlayer_BASE::disposing();
|
||||
}
|
||||
|
||||
QtPlayer::~QtPlayer()
|
||||
{
|
||||
// ensure output objects get deleted as QMediaPlayer doesn't take ownership of them
|
||||
std::unique_ptr<QObject> xVideoWidget(m_xMediaPlayer->videoOutput());
|
||||
std::unique_ptr<QAudioOutput> xAudioOutput(m_xMediaPlayer->audioOutput());
|
||||
m_xMediaPlayer.reset();
|
||||
}
|
||||
|
||||
bool QtPlayer::isReadyToPlay()
|
||||
{
|
||||
assert(m_xMediaPlayer);
|
||||
QMediaPlayer::MediaStatus eStatus = m_xMediaPlayer->mediaStatus();
|
||||
return eStatus == QMediaPlayer::BufferingMedia || eStatus == QMediaPlayer::BufferedMedia
|
||||
|| eStatus == QMediaPlayer::LoadedMedia || eStatus == QMediaPlayer::EndOfMedia;
|
||||
}
|
||||
|
||||
void QtPlayer::installNotify()
|
||||
{
|
||||
connect(m_xMediaPlayer.get(), &QMediaPlayer::mediaStatusChanged, this,
|
||||
&QtPlayer::notifyIfReady);
|
||||
}
|
||||
|
||||
void QtPlayer::uninstallNotify()
|
||||
{
|
||||
disconnect(m_xMediaPlayer.get(), &QMediaPlayer::mediaStatusChanged, this,
|
||||
&QtPlayer::notifyIfReady);
|
||||
}
|
||||
|
||||
void QtPlayer::notifyIfReady(QMediaPlayer::MediaStatus)
|
||||
{
|
||||
if (isReadyToPlay())
|
||||
{
|
||||
rtl::Reference<QtPlayer> xThis(this);
|
||||
xThis->notifyListeners();
|
||||
xThis->uninstallNotify();
|
||||
}
|
||||
}
|
||||
|
||||
void QtPlayer::notifyListeners()
|
||||
{
|
||||
comphelper::OInterfaceContainerHelper2* pContainer
|
||||
= m_lListener.getContainer(cppu::UnoType<css::media::XPlayerListener>::get());
|
||||
if (!pContainer)
|
||||
return;
|
||||
|
||||
css::lang::EventObject aEvent;
|
||||
aEvent.Source = getXWeak();
|
||||
|
||||
comphelper::OInterfaceIteratorHelper2 pIterator(*pContainer);
|
||||
while (pIterator.hasMoreElements())
|
||||
{
|
||||
css::uno::Reference<css::media::XPlayerListener> xListener(
|
||||
static_cast<css::media::XPlayerListener*>(pIterator.next()));
|
||||
xListener->preferredPlayerWindowSizeAvailable(aEvent);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
84
avmedia/source/qt6/QtPlayer.hxx
Normal file
84
avmedia/source/qt6/QtPlayer.hxx
Normal file
|
@ -0,0 +1,84 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sal/config.h>
|
||||
|
||||
#include <QtMultimedia/QMediaPlayer>
|
||||
|
||||
#include <com/sun/star/lang/XServiceInfo.hpp>
|
||||
#include <com/sun/star/media/XPlayer.hpp>
|
||||
#include <com/sun/star/media/XPlayerNotifier.hpp>
|
||||
#include <comphelper/multicontainer2.hxx>
|
||||
#include <cppuhelper/compbase.hxx>
|
||||
#include <cppuhelper/basemutex.hxx>
|
||||
|
||||
namespace avmedia::qt
|
||||
{
|
||||
typedef cppu::WeakComponentImplHelper<css::media::XPlayer, css::media::XPlayerNotifier,
|
||||
css::lang::XServiceInfo>
|
||||
QtPlayer_BASE;
|
||||
|
||||
class QtPlayer final : public QObject, public cppu::BaseMutex, public QtPlayer_BASE
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QtPlayer();
|
||||
~QtPlayer() override;
|
||||
|
||||
bool create(const OUString& rURL);
|
||||
|
||||
// XPlayer
|
||||
virtual void SAL_CALL start() override;
|
||||
virtual void SAL_CALL stop() override;
|
||||
virtual sal_Bool SAL_CALL isPlaying() override;
|
||||
virtual double SAL_CALL getDuration() override;
|
||||
virtual void SAL_CALL setMediaTime(double fTime) override;
|
||||
virtual double SAL_CALL getMediaTime() override;
|
||||
virtual void SAL_CALL setPlaybackLoop(sal_Bool bSet) override;
|
||||
virtual sal_Bool SAL_CALL isPlaybackLoop() override;
|
||||
virtual void SAL_CALL setVolumeDB(sal_Int16 nVolumeDB) override;
|
||||
virtual sal_Int16 SAL_CALL getVolumeDB() override;
|
||||
virtual void SAL_CALL setMute(sal_Bool bSet) override;
|
||||
virtual sal_Bool SAL_CALL isMute() override;
|
||||
virtual css::awt::Size SAL_CALL getPreferredPlayerWindowSize() override;
|
||||
virtual css::uno::Reference<css::media::XPlayerWindow>
|
||||
SAL_CALL createPlayerWindow(const css::uno::Sequence<css::uno::Any>& rArgs) override;
|
||||
virtual css::uno::Reference<css::media::XFrameGrabber> SAL_CALL createFrameGrabber() override;
|
||||
|
||||
// XPlayerNotifier
|
||||
virtual void SAL_CALL
|
||||
addPlayerListener(const css::uno::Reference<css::media::XPlayerListener>& rListener) override;
|
||||
virtual void SAL_CALL removePlayerListener(
|
||||
const css::uno::Reference<css::media::XPlayerListener>& rListener) override;
|
||||
|
||||
// XServiceInfo
|
||||
virtual OUString SAL_CALL getImplementationName() override;
|
||||
virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
|
||||
virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
|
||||
|
||||
virtual void SAL_CALL disposing() final override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<QMediaPlayer> m_xMediaPlayer;
|
||||
comphelper::OMultiTypeInterfaceContainerHelper2 m_lListener;
|
||||
|
||||
bool isReadyToPlay();
|
||||
|
||||
void installNotify();
|
||||
void uninstallNotify();
|
||||
void notifyListeners();
|
||||
void notifyIfReady(QMediaPlayer::MediaStatus eStatus);
|
||||
};
|
||||
|
||||
} // namespace avmedia::qt
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
16
avmedia/source/qt6/avmediaqt.component
Normal file
16
avmedia/source/qt6/avmediaqt.component
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
-->
|
||||
<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
|
||||
xmlns="http://openoffice.org/2010/uno-components">
|
||||
<implementation name="com.sun.star.comp.media.Manager_Qt"
|
||||
constructor="com_sun_star_comp_media_Manager_Qt_get_implementation">
|
||||
<service name="com.sun.star.comp.avmedia.Manager_Qt"/>
|
||||
</implementation>
|
||||
</component>
|
12
avmedia/source/qt6/gstwindow.cxx
Normal file
12
avmedia/source/qt6/gstwindow.cxx
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "../gstreamer/gstwindow.cxx"
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
|
@ -184,8 +184,11 @@ uno::Reference<media::XPlayer> MediaWindowImpl::createPlayer(const OUString& rUR
|
|||
//if (!pMimeType || *pMimeType == AVMEDIA_MIMETYPE_COMMON)
|
||||
{
|
||||
uno::Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext());
|
||||
if (Application::GetToolkitName() == "gtk4")
|
||||
const OUString sToolkitName = Application::GetToolkitName();
|
||||
if (sToolkitName == "gtk4")
|
||||
xPlayer = createPlayer(rURL, u"com.sun.star.comp.avmedia.Manager_Gtk"_ustr, xContext);
|
||||
else if (sToolkitName.startsWith(u"kf6") || sToolkitName.startsWith(u"qt6"))
|
||||
xPlayer = createPlayer(rURL, u"com.sun.star.comp.avmedia.Manager_Qt"_ustr, xContext);
|
||||
else
|
||||
xPlayer = createPlayer(rURL, u"" AVMEDIA_MANAGER_SERVICE_NAME ""_ustr, xContext);
|
||||
}
|
||||
|
|
|
@ -211,6 +211,7 @@ export ENABLE_PDFIUM=@ENABLE_PDFIUM@
|
|||
export ENABLE_POPPLER=@ENABLE_POPPLER@
|
||||
export ENABLE_QT5=@ENABLE_QT5@
|
||||
export ENABLE_QT6=@ENABLE_QT6@
|
||||
export ENABLE_QT6_MULTIMEDIA=@ENABLE_QT6_MULTIMEDIA@
|
||||
export ENABLE_KF5=@ENABLE_KF5@
|
||||
export ENABLE_KF6=@ENABLE_KF6@
|
||||
export ENABLE_GTK3_KDE5=@ENABLE_GTK3_KDE5@
|
||||
|
|
|
@ -29,6 +29,7 @@ Settings about which desktops have support enabled.
|
|||
*/
|
||||
#define USE_HEADLESS_CODE 0
|
||||
#define ENABLE_GSTREAMER_1_0 0
|
||||
#define ENABLE_QT6_MULTIMEDIA 0
|
||||
#define QT5_HAVE_GOBJECT 0
|
||||
#define QT5_USING_X11 0
|
||||
#define QT6_USING_X11 0
|
||||
|
|
19
configure.ac
19
configure.ac
|
@ -1815,6 +1815,10 @@ AC_ARG_ENABLE(qt6,
|
|||
available.]),
|
||||
,)
|
||||
|
||||
AC_ARG_ENABLE(qt6-multimedia,
|
||||
AS_HELP_STRING([--disable-qt6-multimedia],
|
||||
[Determines whether to enable media playback using QtMultimedia when using the qt6/kf6 VCL plugins.]))
|
||||
|
||||
AC_ARG_ENABLE(kf5,
|
||||
AS_HELP_STRING([--enable-kf5],
|
||||
[Determines whether to use Qt5/KF5 vclplug on platforms where Qt5 and
|
||||
|
@ -13419,6 +13423,7 @@ dnl ===================================================================
|
|||
QT6_CFLAGS=""
|
||||
QT6_LIBS=""
|
||||
QT6_PLATFORMS_SRCDIR=""
|
||||
ENABLE_QT6_MULTIMEDIA=""
|
||||
if test \( "$test_kf6" = "yes" -a "$ENABLE_KF6" = "TRUE" \) -o \
|
||||
\( "$test_qt6" = "yes" -a "$ENABLE_QT6" = "TRUE" \)
|
||||
then
|
||||
|
@ -13505,6 +13510,15 @@ then
|
|||
QT6_LIBS="-L$qt6_libdir -lQt6Core -lQt6Gui -lQt6Widgets -lQt6Network"
|
||||
if test "$_os" = "Emscripten"; then
|
||||
QT6_LIBS="$QT6_LIBS -lQt6BundledPcre2 -lQt6BundledZLIB -L${qt6_platformsdir} -lqwasm -sGL_ENABLE_GET_PROC_ADDRESS"
|
||||
else
|
||||
if ! test "$enable_qt6_multimedia" = "no"; then
|
||||
if ! test -r "$qt6_incdir/QtMultimediaWidgets/QVideoWidget"; then
|
||||
AC_MSG_ERROR([Qt 6 QMultimedia not found.])
|
||||
break
|
||||
fi
|
||||
ENABLE_QT6_MULTIMEDIA=TRUE
|
||||
QT6_LIBS="$QT6_LIBS -lQt6Multimedia -lQt6MultimediaWidgets"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$USING_X11" = TRUE; then
|
||||
|
@ -13540,6 +13554,7 @@ AC_SUBST(QT6_CFLAGS)
|
|||
AC_SUBST(QT6_LIBS)
|
||||
AC_SUBST(MOC6)
|
||||
AC_SUBST(QT6_PLATFORMS_SRCDIR)
|
||||
AC_SUBST(ENABLE_QT6_MULTIMEDIA)
|
||||
|
||||
dnl ===================================================================
|
||||
dnl KF5 Integration
|
||||
|
@ -13705,6 +13720,10 @@ fi
|
|||
AC_SUBST(KF6_CFLAGS)
|
||||
AC_SUBST(KF6_LIBS)
|
||||
|
||||
if test "$enable_qt6_multimedia" = "yes" -a "$ENABLE_QT6" != "TRUE"; then
|
||||
AC_MSG_ERROR([--enable-qt6-multimedia requires --enable-qt6 or --enable-kf6])
|
||||
fi
|
||||
|
||||
dnl ===================================================================
|
||||
dnl Test whether to include Evolution 2 support
|
||||
dnl ===================================================================
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QKeyEvent>
|
||||
#include <QtGui/QMouseEvent>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
|
||||
QtObject::QtObject(QtFrame* pParent, bool bShow)
|
||||
: m_pParent(pParent)
|
||||
|
@ -111,6 +112,10 @@ QtObjectWidget::QtObjectWidget(QtObject& rParent)
|
|||
assert(m_rParent.frame() && m_rParent.frame()->GetQWidget());
|
||||
setAttribute(Qt::WA_NoSystemBackground);
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
|
||||
// set layout, used for video playback, see QtPlayer::createPlayerWindow
|
||||
QVBoxLayout* layout = new QVBoxLayout;
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
void QtObjectWidget::focusInEvent(QFocusEvent*)
|
||||
|
|
Loading…
Reference in a new issue