Repository.mk                              |    1 
 avmedia/Library_avmediagtk.mk              |   48 +++
 avmedia/Module_avmedia.mk                  |    6 
 avmedia/source/gstreamer/gstwindow.cxx     |    1 
 avmedia/source/gstreamer/gstwindow.hxx     |    2 
 avmedia/source/gtk/avmediagtk.component    |   16 +
 avmedia/source/gtk/gstwindow.cxx           |   12 
 avmedia/source/gtk/gtkmanager.cxx          |   61 ++++
 avmedia/source/gtk/gtkmanager.hxx          |   34 ++
 avmedia/source/gtk/gtkplayer.cxx           |  384 +++++++++++++++++++++++++++++
 avmedia/source/gtk/gtkplayer.hxx           |   71 +++++
 avmedia/source/viewer/mediawindow_impl.cxx |    6 
 compilerplugins/clang/reservedid.cxx       |    4 
 include/sal/log-areas.dox                  |    1 
 14 files changed, 644 insertions(+), 3 deletions(-)

New commits:
commit d0a527ec09516bc7215baf229adb90cd21ffa27a
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Thu Feb 10 12:55:18 2022 +0000
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Fri Feb 18 20:40:01 2022 +0100

    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 <caol...@redhat.com>

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

Reply via email to