tdf#145735 qt avmedia: Show audio placeholder for audio files

So far, `QtPlayer::createPlayerWindow` was unconditionally
creating a video widget.

However, audio-only media files can be used as well,
therefore handle that case, too and create a widget
holding an audio icon as a placeholder instead if
the media doesn't contain video.
(This is the same icon shown when using qt5 that
doesn't use QtMultimedia).

As described in

    commit a99575f04f
    Author: Michael Weghorn <m.weghorn@posteo.de>
    Date:   Sat Jun 1 07:32:22 2024 +0200

        tdf#194504 qt avmedia: Don't wait for video frame if there's none

, `QMediaPlayer::hasVideo()` only returns a useful
result once loading media has finished. Therefore,
if the player is still in that state in
`QtPlayer::createPlayerWindow`, defer
creating the widget to when the media status
changes.

With this commit in place, opening an Impress presentation
that contains an audio file (like attachment 194504
from tdf#145735) and starting presentation mode now shows an
"audio icon" as placeholder as expected when using
the qt6 VCL plugin.

(This commit here makes that work for presentation
mode, while the above-mentioned commit already made
the icon show as expected for non-presentation mode.)

Change-Id: I1ff7e8b8659162a748abc3f97a8d2181375c0e7c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169009
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
This commit is contained in:
Michael Weghorn
2024-06-17 16:27:56 +02:00
parent ca364f8f16
commit 12c4b7ee91
2 changed files with 75 additions and 11 deletions

View File

@@ -13,6 +13,7 @@
#include <QtMultimedia/QAudioOutput>
#include <QtMultimedia/QMediaMetaData>
#include <QtMultimediaWidgets/QVideoWidget>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLayout>
#include <cppuhelper/supportsservice.hxx>
@@ -20,6 +21,7 @@
#include <rtl/string.hxx>
#include <tools/link.hxx>
#include <vcl/BitmapTools.hxx>
#include <vcl/filter/PngImageWriter.hxx>
#include <vcl/graph.hxx>
#include <vcl/svapp.hxx>
#include <vcl/syschild.hxx>
@@ -47,6 +49,7 @@ namespace avmedia::qt
QtPlayer::QtPlayer()
: QtPlayer_BASE(m_aMutex)
, m_lListener(m_aMutex)
, m_pMediaWidgetParent(nullptr)
{
}
@@ -197,6 +200,9 @@ uno::Reference<::media::XPlayerWindow>
{
osl::MutexGuard aGuard(m_aMutex);
if (rArguments.getLength() > 1)
rArguments[1] >>= m_aPlayerWidgetRect;
if (rArguments.getLength() <= 2)
{
uno::Reference<::media::XPlayerWindow> xRet = new ::avmedia::gstreamer::Window;
@@ -213,18 +219,20 @@ uno::Reference<::media::XPlayerWindow>
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);
m_pMediaWidgetParent = static_cast<QWidget*>(pParentEnvData->pWidget);
assert(m_pMediaWidgetParent);
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);
// while media is loading, QMediaPlayer::hasVideo doesn't yet return
// whether media actually has video; defer creating audio/video widget
if (m_xMediaPlayer->mediaStatus() == QMediaPlayer::LoadingMedia)
{
connect(m_xMediaPlayer.get(), &QMediaPlayer::mediaStatusChanged, this,
&QtPlayer::createMediaPlayerWidget, Qt::SingleShotConnection);
}
else
{
createMediaPlayerWidget();
}
uno::Reference<::media::XPlayerWindow> xRet = new ::avmedia::gstreamer::Window;
return xRet;
@@ -320,6 +328,55 @@ void QtPlayer::notifyIfReady(QMediaPlayer::MediaStatus)
}
}
void QtPlayer::createMediaPlayerWidget()
{
assert(m_xMediaPlayer);
assert(m_xMediaPlayer->mediaStatus() != QMediaPlayer::LoadingMedia
&& "Media is still loading, detecting video availability not possible.");
assert(m_pMediaWidgetParent && "Parent for media widget not set");
// if media contains video, show the video output,
// otherwise show an audio icon as a placeholder
QWidget* pWidget;
if (m_xMediaPlayer->hasVideo())
{
QVideoWidget* pVideoWidget = new QVideoWidget(m_pMediaWidgetParent);
pVideoWidget->setAspectRatioMode(Qt::IgnoreAspectRatio);
assert(!m_xMediaPlayer->videoOutput() && "Video output already set.");
m_xMediaPlayer->setVideoOutput(pVideoWidget);
pWidget = pVideoWidget;
}
else
{
BitmapEx aPlaceholderIcon(u"avmedia/res/avaudiologo.png"_ustr);
SvMemoryStream aMemoryStream;
vcl::PngImageWriter aWriter(aMemoryStream);
aWriter.write(aPlaceholderIcon);
QPixmap aAudioPixmap;
aAudioPixmap.loadFromData(static_cast<const uchar*>(aMemoryStream.GetData()),
aMemoryStream.TellEnd());
assert(!aAudioPixmap.isNull() && "Failed to load audio logo");
aAudioPixmap
= aAudioPixmap.scaled(QSize(m_aPlayerWidgetRect.Width, m_aPlayerWidgetRect.Height));
QLabel* pLabel = new QLabel;
pLabel->setPixmap(aAudioPixmap);
pWidget = pLabel;
}
assert(pWidget);
pWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
// retrieve the layout (which is set in the QtObjectWidget ctor)
QLayout* pLayout = m_pMediaWidgetParent->layout();
assert(pLayout);
assert(pLayout->count() == 0 && "Layout already has a widget set");
pLayout->addWidget(pWidget);
}
void QtPlayer::notifyListeners()
{
comphelper::OInterfaceContainerHelper2* pContainer

View File

@@ -12,6 +12,7 @@
#include <sal/config.h>
#include <QtMultimedia/QMediaPlayer>
#include <QtWidgets/QWidget>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/media/XPlayer.hpp>
@@ -71,6 +72,12 @@ private:
std::unique_ptr<QMediaPlayer> m_xMediaPlayer;
comphelper::OMultiTypeInterfaceContainerHelper2 m_lListener;
// area to use for the player widget
css::awt::Rectangle m_aPlayerWidgetRect;
QWidget* m_pMediaWidgetParent;
void createMediaPlayerWidget();
bool isReadyToPlay();
void installNotify();