summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2022-02-10 12:55:18 +0000
committerCaolán McNamara <caolanm@redhat.com>2022-02-18 20:40:01 +0100
commitd0a527ec09516bc7215baf229adb90cd21ffa27a (patch)
tree2ce0dc20f847e8d14805ce70f466606cf60e4840
parentthere's only one media backend per platform currently (diff)
downloadcore-d0a527ec09516bc7215baf229adb90cd21ffa27a.tar.gz
core-d0a527ec09516bc7215baf229adb90cd21ffa27a.zip
first cut at using Gtk4 built in video playback
Change-Id: Ib996cd3f5ddbf20a81cdbe4b1c6546d6df478fde Reviewed-on: https://gerrit.libreoffice.org/c/core/+/129783 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r--Repository.mk1
-rw-r--r--avmedia/Library_avmediagtk.mk48
-rw-r--r--avmedia/Module_avmedia.mk6
-rw-r--r--avmedia/source/gstreamer/gstwindow.cxx1
-rw-r--r--avmedia/source/gstreamer/gstwindow.hxx2
-rw-r--r--avmedia/source/gtk/avmediagtk.component16
-rw-r--r--avmedia/source/gtk/gstwindow.cxx12
-rw-r--r--avmedia/source/gtk/gtkmanager.cxx61
-rw-r--r--avmedia/source/gtk/gtkmanager.hxx34
-rw-r--r--avmedia/source/gtk/gtkplayer.cxx384
-rw-r--r--avmedia/source/gtk/gtkplayer.hxx71
-rw-r--r--avmedia/source/viewer/mediawindow_impl.cxx6
-rw-r--r--compilerplugins/clang/reservedid.cxx4
-rw-r--r--include/sal/log-areas.dox1
14 files changed, 644 insertions, 3 deletions
diff --git a/Repository.mk b/Repository.mk
index aa654ce9c80d..ea2a55aeff6f 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -643,6 +643,7 @@ endif
$(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 $(filter WNT,$(OS)),avmediawin) \
) \
cached1 \
diff --git a/avmedia/Library_avmediagtk.mk b/avmedia/Library_avmediagtk.mk
new file mode 100644
index 000000000000..08d30d3259dc
--- /dev/null
+++ b/avmedia/Library_avmediagtk.mk
@@ -0,0 +1,48 @@
+# -*- 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,avmediagtk))
+
+$(eval $(call gb_Library_set_componentfile,avmediagtk,avmedia/source/gtk/avmediagtk,services))
+
+$(eval $(call gb_Library_set_include,avmediagtk,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/avmedia/source/inc \
+ -I$(SRCDIR)/avmedia/source/gstreamer \
+))
+
+$(eval $(call gb_Library_use_external,avmediagtk,boost_headers))
+
+$(eval $(call gb_Library_add_cxxflags,avmediagtk,\
+ $$(GTK4_CFLAGS) \
+))
+
+$(eval $(call gb_Library_use_sdk_api,avmediagtk))
+
+$(eval $(call gb_Library_use_libraries,avmediagtk,\
+ comphelper \
+ cppu \
+ cppuhelper \
+ sal \
+ salhelper \
+ tl \
+ vcl \
+))
+
+$(eval $(call gb_Library_add_libs,avmediagtk,\
+ $(GTK4_LIBS) \
+))
+
+$(eval $(call gb_Library_add_exception_objects,avmediagtk,\
+ avmedia/source/gtk/gstwindow \
+ avmedia/source/gtk/gtkmanager \
+ avmedia/source/gtk/gtkplayer \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/avmedia/Module_avmedia.mk b/avmedia/Module_avmedia.mk
index d01201582a78..8a1132077210 100644
--- a/avmedia/Module_avmedia.mk
+++ b/avmedia/Module_avmedia.mk
@@ -25,6 +25,12 @@ $(eval $(call gb_Module_add_targets,avmedia,\
))
endif
+ifneq ($(ENABLE_GTK4),)
+$(eval $(call gb_Module_add_targets,avmedia,\
+ Library_avmediagtk \
+))
+endif
+
ifeq ($(OS),MACOSX)
$(eval $(call gb_Module_add_targets,avmedia,\
Library_avmediaMacAVF \
diff --git a/avmedia/source/gstreamer/gstwindow.cxx b/avmedia/source/gstreamer/gstwindow.cxx
index 5f7958e723c3..5862443da6aa 100644
--- a/avmedia/source/gstreamer/gstwindow.cxx
+++ b/avmedia/source/gstreamer/gstwindow.cxx
@@ -22,7 +22,6 @@
#include <cppuhelper/supportsservice.hxx>
#include "gstwindow.hxx"
-#include "gstplayer.hxx"
constexpr OUStringLiteral AVMEDIA_GST_WINDOW_IMPLEMENTATIONNAME = u"com.sun.star.comp.avmedia.Window_GStreamer";
constexpr OUStringLiteral AVMEDIA_GST_WINDOW_SERVICENAME = u"com.sun.star.media.Window_GStreamer";
diff --git a/avmedia/source/gstreamer/gstwindow.hxx b/avmedia/source/gstreamer/gstwindow.hxx
index c9d633d5434f..ff8a7cc91566 100644
--- a/avmedia/source/gstreamer/gstwindow.hxx
+++ b/avmedia/source/gstreamer/gstwindow.hxx
@@ -19,10 +19,10 @@
#pragma once
-#include "gstcommon.hxx"
#include <cppuhelper/implbase.hxx>
#include <cppuhelper/interfacecontainer.h>
+#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/media/XPlayerWindow.hpp>
namespace avmedia::gstreamer {
diff --git a/avmedia/source/gtk/avmediagtk.component b/avmedia/source/gtk/avmediagtk.component
new file mode 100644
index 000000000000..e3930dc9e65d
--- /dev/null
+++ b/avmedia/source/gtk/avmediagtk.component
@@ -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_Gtk"
+ constructor="com_sun_star_comp_media_Manager_Gtk_get_implementation">
+ <service name="com.sun.star.comp.avmedia.Manager_Gtk"/>
+ </implementation>
+</component>
diff --git a/avmedia/source/gtk/gstwindow.cxx b/avmedia/source/gtk/gstwindow.cxx
new file mode 100644
index 000000000000..48c70df98e7d
--- /dev/null
+++ b/avmedia/source/gtk/gstwindow.cxx
@@ -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: */
diff --git a/avmedia/source/gtk/gtkmanager.cxx b/avmedia/source/gtk/gtkmanager.cxx
new file mode 100644
index 000000000000..5beff87e164a
--- /dev/null
+++ b/avmedia/source/gtk/gtkmanager.cxx
@@ -0,0 +1,61 @@
+/* -*- 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 <cppuhelper/supportsservice.hxx>
+
+#include "gtkmanager.hxx"
+#include "gtkplayer.hxx"
+
+#include <tools/urlobj.hxx>
+#include <rtl/ref.hxx>
+
+using namespace ::com::sun::star;
+
+namespace avmedia::gtk
+{
+Manager::Manager() {}
+
+Manager::~Manager() {}
+
+uno::Reference<media::XPlayer> SAL_CALL Manager::createPlayer(const OUString& rURL)
+{
+ const INetURLObject aURL(rURL);
+ OUString sMainURL = aURL.GetMainURL(INetURLObject::DecodeMechanism::Unambiguous);
+
+ rtl::Reference<GtkPlayer> xPlayer(new GtkPlayer);
+ if (!xPlayer->create(sMainURL))
+ xPlayer.clear();
+ return xPlayer;
+}
+
+OUString SAL_CALL Manager::getImplementationName()
+{
+ return "com.sun.star.comp.avmedia.ManagerGtk";
+}
+
+sal_Bool SAL_CALL Manager::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL Manager::getSupportedServiceNames()
+{
+ return { "com.sun.star.media.Manager" };
+}
+
+} // namespace
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_media_Manager_Gtk_get_implementation(css::uno::XComponentContext*,
+ css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new avmedia::gtk::Manager());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/avmedia/source/gtk/gtkmanager.hxx b/avmedia/source/gtk/gtkmanager.hxx
new file mode 100644
index 000000000000..9cf6d93f5b68
--- /dev/null
+++ b/avmedia/source/gtk/gtkmanager.hxx
@@ -0,0 +1,34 @@
+/* -*- 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 <cppuhelper/implbase.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/media/XManager.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+namespace avmedia::gtk
+{
+class Manager : public cppu::WeakImplHelper<css::media::XManager, css::lang::XServiceInfo>
+{
+public:
+ explicit Manager();
+ virtual ~Manager() 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: */
diff --git a/avmedia/source/gtk/gtkplayer.cxx b/avmedia/source/gtk/gtkplayer.cxx
new file mode 100644
index 000000000000..b01eaeeed630
--- /dev/null
+++ b/avmedia/source/gtk/gtkplayer.cxx
@@ -0,0 +1,384 @@
+/* -*- 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 <mutex>
+
+#include <cppuhelper/supportsservice.hxx>
+#include <sal/log.hxx>
+#include <vcl/BitmapTools.hxx>
+#include <rtl/string.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/syschild.hxx>
+#include <vcl/sysdata.hxx>
+
+#include <gstwindow.hxx>
+#include "gtkplayer.hxx"
+
+#include <gtk/gtk.h>
+
+constexpr OUStringLiteral AVMEDIA_GTK_PLAYER_IMPLEMENTATIONNAME
+ = u"com.sun.star.comp.avmedia.Player_Gtk";
+constexpr OUStringLiteral AVMEDIA_GTK_PLAYER_SERVICENAME = u"com.sun.star.media.Player_Gtk";
+
+using namespace ::com::sun::star;
+
+namespace avmedia::gtk
+{
+GtkPlayer::GtkPlayer()
+ : GtkPlayer_BASE(m_aMutex)
+ , m_pStream(nullptr)
+ , m_pVideo(nullptr)
+ , m_nUnmutedVolume(0)
+{
+}
+
+GtkPlayer::~GtkPlayer() { disposing(); }
+
+static gboolean gtk_media_stream_unref(gpointer user_data)
+{
+ g_object_unref(user_data);
+ return FALSE;
+}
+
+void GtkPlayer::cleanup()
+{
+ if (m_pVideo)
+ {
+ gtk_widget_unparent(m_pVideo);
+ m_pVideo = nullptr;
+ }
+
+ if (m_pStream)
+ {
+ // shouldn't have to attempt this unref on idle, but with gtk4-4.4.1 I get
+ // intermittent "instance of invalid non-instantiatable type '(null)'"
+ // on some mysterious gst dbus callback
+ if (g_main_context_default())
+ g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, gtk_media_stream_unref, m_pStream, nullptr);
+ else
+ g_object_unref(m_pStream);
+ m_pStream = nullptr;
+ }
+}
+
+void SAL_CALL GtkPlayer::disposing()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ stop();
+
+ cleanup();
+}
+
+bool GtkPlayer::create(const OUString& rURL)
+{
+ bool bRet = false;
+
+ cleanup();
+
+ if (!rURL.isEmpty())
+ {
+ GFile* pFile = g_file_new_for_uri(OUStringToOString(rURL, RTL_TEXTENCODING_UTF8).getStr());
+ m_pStream = gtk_media_file_new_for_file(pFile);
+ g_object_unref(pFile);
+
+ bRet = gtk_media_stream_get_error(m_pStream) == nullptr;
+ }
+
+ if (bRet)
+ m_aURL = rURL;
+ else
+ m_aURL.clear();
+
+ return bRet;
+}
+
+void SAL_CALL GtkPlayer::start()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ if (m_pStream)
+ gtk_media_stream_play(m_pStream);
+}
+
+void SAL_CALL GtkPlayer::stop()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ if (m_pStream)
+ gtk_media_stream_pause(m_pStream);
+}
+
+sal_Bool SAL_CALL GtkPlayer::isPlaying()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ bool bRet = false;
+
+ if (m_pStream)
+ bRet = gtk_media_stream_get_playing(m_pStream);
+
+ return bRet;
+}
+
+double SAL_CALL GtkPlayer::getDuration()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ double duration = 0.0;
+
+ if (m_pStream)
+ duration = gtk_media_stream_get_duration(m_pStream) / 1000000.0;
+
+ return duration;
+}
+
+void SAL_CALL GtkPlayer::setMediaTime(double fTime)
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ if (!m_pStream)
+ return;
+
+ gint64 gst_position = llround(fTime * 1000000);
+
+ gtk_media_stream_seek(m_pStream, gst_position);
+
+ // on resetting back to zero the reported timestamp doesn't seem to get
+ // updated in a reasonable time, so on zero just force an update of
+ // timestamp to 0
+ if (gst_position == 0 && gtk_media_stream_is_prepared(m_pStream))
+ gtk_media_stream_update(m_pStream, gst_position);
+}
+
+double SAL_CALL GtkPlayer::getMediaTime()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ double position = 0.0;
+
+ if (m_pStream)
+ position = gtk_media_stream_get_timestamp(m_pStream) / 1000000.0;
+
+ return position;
+}
+
+void SAL_CALL GtkPlayer::setPlaybackLoop(sal_Bool bSet)
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ gtk_media_stream_set_loop(m_pStream, bSet);
+}
+
+sal_Bool SAL_CALL GtkPlayer::isPlaybackLoop()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ return gtk_media_stream_get_loop(m_pStream);
+}
+
+// gtk4-4.4.1 docs state: "Muting a stream will cause no audio to be played, but
+// it does not modify the volume. This means that muting and then unmuting the
+// stream will restore the volume settings." but that doesn't seem to be my
+// experience at all
+void SAL_CALL GtkPlayer::setMute(sal_Bool bSet)
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ bool bMuted = gtk_media_stream_get_muted(m_pStream);
+ if (bMuted == static_cast<bool>(bSet))
+ return;
+ gtk_media_stream_set_muted(m_pStream, bSet);
+ if (!bSet)
+ setVolumeDB(m_nUnmutedVolume);
+}
+
+sal_Bool SAL_CALL GtkPlayer::isMute()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ return gtk_media_stream_get_muted(m_pStream);
+}
+
+void SAL_CALL GtkPlayer::setVolumeDB(sal_Int16 nVolumeDB)
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ // range is -40 for silence to 0 for full volume
+ m_nUnmutedVolume = std::clamp<sal_Int16>(nVolumeDB, -40, 0);
+ double fValue = (m_nUnmutedVolume + 40) / 40.0;
+ gtk_media_stream_set_volume(m_pStream, fValue);
+}
+
+sal_Int16 SAL_CALL GtkPlayer::getVolumeDB()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ if (gtk_media_stream_get_muted(m_pStream))
+ return m_nUnmutedVolume;
+
+ double fVolume = gtk_media_stream_get_volume(m_pStream);
+
+ m_nUnmutedVolume = (fVolume * 40) - 40;
+
+ return m_nUnmutedVolume;
+}
+
+awt::Size SAL_CALL GtkPlayer::getPreferredPlayerWindowSize()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ awt::Size aSize(0, 0);
+
+ if (m_pStream)
+ {
+ aSize.Width = gdk_paintable_get_intrinsic_width(GDK_PAINTABLE(m_pStream));
+ aSize.Height = gdk_paintable_get_intrinsic_height(GDK_PAINTABLE(m_pStream));
+ }
+
+ return aSize;
+}
+
+uno::Reference<::media::XPlayerWindow>
+ SAL_CALL GtkPlayer::createPlayerWindow(const uno::Sequence<uno::Any>& rArguments)
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ uno::Reference<::media::XPlayerWindow> xRet;
+
+ if (rArguments.getLength() > 1)
+ rArguments[1] >>= m_aArea;
+
+ if (rArguments.getLength() <= 2)
+ {
+ 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* pEnvData = pParentWindow->GetSystemData();
+ if (!pEnvData)
+ return nullptr;
+
+ m_pVideo = gtk_picture_new_for_paintable(GDK_PAINTABLE(m_pStream));
+ gtk_widget_set_vexpand(m_pVideo, true);
+ gtk_widget_set_hexpand(m_pVideo, true);
+
+ GtkWidget* pParent = static_cast<GtkWidget*>(pEnvData->pWidget);
+ gtk_grid_attach(GTK_GRID(pParent), m_pVideo, 0, 0, 1, 1);
+ gtk_widget_show(m_pVideo);
+ gtk_widget_show(pParent);
+
+ xRet = new ::avmedia::gstreamer::Window;
+
+ return xRet;
+}
+
+namespace
+{
+class GtkFrameGrabber : public ::cppu::WeakImplHelper<css::media::XFrameGrabber>
+{
+ GtkMediaStream* m_pStream;
+
+public:
+ GtkFrameGrabber(GtkMediaStream* pStream)
+ : m_pStream(pStream)
+ {
+ }
+
+ // XFrameGrabber
+ virtual css::uno::Reference<css::graphic::XGraphic>
+ SAL_CALL grabFrame(double fMediaTime) override
+ {
+ GtkWidget* pWindow = gtk_window_new();
+ GtkWidget* pVideo = gtk_picture_new_for_paintable(GDK_PAINTABLE(m_pStream));
+ gtk_window_set_child(GTK_WINDOW(pWindow), pVideo);
+ gtk_widget_realize(pVideo);
+ gtk_widget_map(pVideo);
+
+ //bool bMuted = gtk_media_stream_get_muted(m_pStream);
+ gtk_media_stream_set_muted(m_pStream, true);
+ gtk_media_stream_set_volume(m_pStream, 0);
+ gint64 gst_position = llround(fMediaTime * 1000000);
+ gtk_media_stream_seek(m_pStream, gst_position);
+ gtk_media_stream_play(m_pStream);
+
+ // while (!gtk_media_stream_is_prepared(m_pStream))
+ // Application::Yield();
+
+ gtk_media_stream_pause(m_pStream);
+
+ GdkPaintable* current_paintable = gdk_paintable_get_current_image(GDK_PAINTABLE(m_pStream));
+
+ // gtk_media_stream_set_muted(m_pStream, bMuted);
+
+ Size aSize(200, 200);
+ cairo_surface_t* surface
+ = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, aSize.Width(), aSize.Height());
+
+ GtkSnapshot* snapshot = gtk_snapshot_new();
+ gdk_paintable_snapshot(current_paintable, snapshot, aSize.Width(), aSize.Height());
+ GskRenderNode* node = gtk_snapshot_free_to_node(snapshot);
+
+ cairo_t* cr = cairo_create(surface);
+ gsk_render_node_draw(node, cr);
+ cairo_destroy(cr);
+
+ gsk_render_node_unref(node);
+ g_object_unref(current_paintable);
+
+ std::unique_ptr<BitmapEx> xBitmap(vcl::bitmap::CreateFromCairoSurface(aSize, surface));
+
+ cairo_surface_destroy(surface);
+
+ gtk_window_destroy(GTK_WINDOW(pWindow));
+
+ return Graphic(*xBitmap).GetXGraphic();
+ }
+};
+}
+
+uno::Reference<media::XFrameGrabber> SAL_CALL GtkPlayer::createFrameGrabber()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ rtl::Reference<GtkFrameGrabber> xFrameGrabber;
+ SAL_WARN("avmedia.gtk", "TODO: createFrameGrabber");
+
+ const awt::Size aPrefSize(getPreferredPlayerWindowSize());
+
+ xFrameGrabber.set(new GtkFrameGrabber(m_pStream));
+
+ // if( ( aPrefSize.Width > 0 ) && ( aPrefSize.Height > 0 ) )
+ // pFrameGrabber = FrameGrabber::create( maURL );
+
+ return xFrameGrabber;
+}
+
+OUString SAL_CALL GtkPlayer::getImplementationName()
+{
+ return AVMEDIA_GTK_PLAYER_IMPLEMENTATIONNAME;
+}
+
+sal_Bool SAL_CALL GtkPlayer::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL GtkPlayer::getSupportedServiceNames()
+{
+ return { AVMEDIA_GTK_PLAYER_SERVICENAME };
+}
+
+} // namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/avmedia/source/gtk/gtkplayer.hxx b/avmedia/source/gtk/gtkplayer.hxx
new file mode 100644
index 000000000000..89f9355c94ae
--- /dev/null
+++ b/avmedia/source/gtk/gtkplayer.hxx
@@ -0,0 +1,71 @@
+/* -*- 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 <string_view>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/media/XPlayer.hpp>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/basemutex.hxx>
+
+typedef struct _GtkMediaStream GtkMediaStream;
+typedef struct _GtkWidget GtkWidget;
+
+namespace avmedia::gtk
+{
+typedef cppu::WeakComponentImplHelper<css::media::XPlayer, css::lang::XServiceInfo> GtkPlayer_BASE;
+
+class GtkPlayer final : public cppu::BaseMutex, public GtkPlayer_BASE
+{
+public:
+ explicit GtkPlayer();
+ virtual ~GtkPlayer() override;
+
+ bool create(const OUString& rURL);
+
+ 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 setMute(sal_Bool bSet) override;
+ virtual sal_Bool SAL_CALL isMute() override;
+ virtual void SAL_CALL setVolumeDB(sal_Int16 nVolumeDB) override;
+ virtual sal_Int16 SAL_CALL getVolumeDB() 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;
+
+ 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:
+ void cleanup();
+
+ OUString m_aURL;
+ css::awt::Rectangle m_aArea; // Area of the player window.
+ GtkMediaStream* m_pStream;
+ GtkWidget* m_pVideo;
+ sal_Int16 m_nUnmutedVolume;
+};
+
+} // namespace avmedia::gtk
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/avmedia/source/viewer/mediawindow_impl.cxx b/avmedia/source/viewer/mediawindow_impl.cxx
index 7f3ec8a4f078..feb28e4e7d39 100644
--- a/avmedia/source/viewer/mediawindow_impl.cxx
+++ b/avmedia/source/viewer/mediawindow_impl.cxx
@@ -37,6 +37,7 @@
#include <vcl/commandevent.hxx>
#include <vcl/event.hxx>
#include <vcl/ptrstyle.hxx>
+#include <vcl/svapp.hxx>
#include <com/sun/star/awt/SystemPointer.hpp>
#include <com/sun/star/lang/XComponent.hpp>
@@ -181,7 +182,10 @@ uno::Reference<media::XPlayer> MediaWindowImpl::createPlayer(const OUString& rUR
if (!pMimeType || *pMimeType == AVMEDIA_MIMETYPE_COMMON)
{
uno::Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext());
- xPlayer = createPlayer(rURL, AVMEDIA_MANAGER_SERVICE_NAME, xContext);
+ if (Application::GetToolkitName() == "gtk4")
+ xPlayer = createPlayer(rURL, "com.sun.star.comp.avmedia.Manager_Gtk", xContext);
+ else
+ xPlayer = createPlayer(rURL, AVMEDIA_MANAGER_SERVICE_NAME, xContext);
}
return xPlayer;
diff --git a/compilerplugins/clang/reservedid.cxx b/compilerplugins/clang/reservedid.cxx
index a5790849f02b..69f5da564eec 100644
--- a/compilerplugins/clang/reservedid.cxx
+++ b/compilerplugins/clang/reservedid.cxx
@@ -209,6 +209,10 @@ bool ReservedId::VisitNamedDecl(NamedDecl const * decl) {
// vcl/unx/gtk/xid_fullscreen_on_all_monitors.c
&& s != "_GstVideoOverlay"
// avmedia/source/gstreamer/gstplayer.hxx
+ && s != "_GtkMediaStream"
+ // avmedia/source/gtk/gtkplayer.hxx
+ && s != "_GtkWidget"
+ // avmedia/source/gtk/gtkplayer.hxx
&& s != "_Module" // extensions/source/activex/StdAfx2.h, CComModule
&& s != "_NotifyingLayout" // vcl/unx/gtk4/notifyinglayout.cxx
&& s != "_SurfacePaintable" // vcl/unx/gtk3/gtkinst.cxx
diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox
index 174a7ca3ca15..7d61cfd3d3cd 100644
--- a/include/sal/log-areas.dox
+++ b/include/sal/log-areas.dox
@@ -600,6 +600,7 @@ certain functionality.
@li @c avmedia
@li @c avmedia.gstreamer
+@li @c avmedia.gtk
@li @c avmedia.quicktime
@section other