Title: [283437] trunk/Source
Revision
283437
Author
[email protected]
Date
2021-10-02 02:07:12 -0700 (Sat, 02 Oct 2021)

Log Message

[GLib] Media session manager unable to handle more than one session
https://bugs.webkit.org/show_bug.cgi?id=230250

Patch by Philippe Normand <[email protected]> on 2021-10-02
Reviewed by Adrian Perez de Castro.

Source/WebCore:

Each session now maintains its own connection to the D-Bus session, allowing to safely
expose the corresponding MPRIS objecs on the bus. Most of the D-Bus and GVariant handling
has been refactored to the new MediaSessionGLib module.

* platform/SourcesGLib.txt:
* platform/audio/glib/MediaSessionGLib.cpp: Added.
(WebCore::getCommand):
(WebCore::handleMethodCall):
(WebCore::getMprisProperty):
(WebCore::handleGetProperty):
(WebCore::handleSetProperty):
(WebCore::MediaSessionGLib::create):
(WebCore::MediaSessionGLib::MediaSessionGLib):
(WebCore::MediaSessionGLib::~MediaSessionGLib):
(WebCore::MediaSessionGLib::nameLost):
(WebCore::MediaSessionGLib::emitPositionChanged):
(WebCore::MediaSessionGLib::updateNowPlaying):
(WebCore::MediaSessionGLib::getMetadataAsGVariant):
(WebCore::MediaSessionGLib::getPlaybackStatusAsGVariant):
(WebCore::MediaSessionGLib::emitPropertiesChanged):
(WebCore::MediaSessionGLib::playbackStatusChanged):
(WebCore::MediaSessionGLib::getActiveSessionPosition):
* platform/audio/glib/MediaSessionGLib.h: Added.
(WebCore::MediaSessionGLib::manager const):
* platform/audio/glib/MediaSessionManagerGLib.cpp:
(WebCore::PlatformMediaSessionManager::create):
(WebCore::MediaSessionManagerGLib::MediaSessionManagerGLib):
(WebCore::MediaSessionManagerGLib::addSession):
(WebCore::MediaSessionManagerGLib::removeSession):
(WebCore::MediaSessionManagerGLib::sessionStateChanged):
(WebCore::MediaSessionManagerGLib::clientCharacteristicsChanged):
(WebCore::MediaSessionManagerGLib::updateNowPlayingInfo):
* platform/audio/glib/MediaSessionManagerGLib.h:
(WebCore::MediaSessionManagerGLib::mprisInterface const):

Source/WTF:

* wtf/glib/GRefPtr.h: Forward-declare GDBusConnection.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (283436 => 283437)


--- trunk/Source/WTF/ChangeLog	2021-10-02 09:04:16 UTC (rev 283436)
+++ trunk/Source/WTF/ChangeLog	2021-10-02 09:07:12 UTC (rev 283437)
@@ -1,3 +1,12 @@
+2021-10-02  Philippe Normand  <[email protected]>
+
+        [GLib] Media session manager unable to handle more than one session
+        https://bugs.webkit.org/show_bug.cgi?id=230250
+
+        Reviewed by Adrian Perez de Castro.
+
+        * wtf/glib/GRefPtr.h: Forward-declare GDBusConnection.
+
 2021-10-01  Yusuke Suzuki  <[email protected]>
 
         Upgrade in-tree OSS ICU header to 64.2 because macOS Mojave build will be dropped

Modified: trunk/Source/WTF/wtf/glib/GRefPtr.h (283436 => 283437)


--- trunk/Source/WTF/wtf/glib/GRefPtr.h	2021-10-02 09:04:16 UTC (rev 283436)
+++ trunk/Source/WTF/wtf/glib/GRefPtr.h	2021-10-02 09:07:12 UTC (rev 283437)
@@ -29,6 +29,7 @@
 #include <wtf/HashTraits.h>
 
 extern "C" {
+    typedef struct _GDBusConnection GDBusConnection;
     typedef struct _GDBusNodeInfo GDBusNodeInfo;
     GDBusNodeInfo* g_dbus_node_info_ref(GDBusNodeInfo*);
     void g_dbus_node_info_unref(GDBusNodeInfo*);

Modified: trunk/Source/WebCore/ChangeLog (283436 => 283437)


--- trunk/Source/WebCore/ChangeLog	2021-10-02 09:04:16 UTC (rev 283436)
+++ trunk/Source/WebCore/ChangeLog	2021-10-02 09:07:12 UTC (rev 283437)
@@ -1,3 +1,45 @@
+2021-10-02  Philippe Normand  <[email protected]>
+
+        [GLib] Media session manager unable to handle more than one session
+        https://bugs.webkit.org/show_bug.cgi?id=230250
+
+        Reviewed by Adrian Perez de Castro.
+
+        Each session now maintains its own connection to the D-Bus session, allowing to safely
+        expose the corresponding MPRIS objecs on the bus. Most of the D-Bus and GVariant handling
+        has been refactored to the new MediaSessionGLib module.
+
+        * platform/SourcesGLib.txt:
+        * platform/audio/glib/MediaSessionGLib.cpp: Added.
+        (WebCore::getCommand):
+        (WebCore::handleMethodCall):
+        (WebCore::getMprisProperty):
+        (WebCore::handleGetProperty):
+        (WebCore::handleSetProperty):
+        (WebCore::MediaSessionGLib::create):
+        (WebCore::MediaSessionGLib::MediaSessionGLib):
+        (WebCore::MediaSessionGLib::~MediaSessionGLib):
+        (WebCore::MediaSessionGLib::nameLost):
+        (WebCore::MediaSessionGLib::emitPositionChanged):
+        (WebCore::MediaSessionGLib::updateNowPlaying):
+        (WebCore::MediaSessionGLib::getMetadataAsGVariant):
+        (WebCore::MediaSessionGLib::getPlaybackStatusAsGVariant):
+        (WebCore::MediaSessionGLib::emitPropertiesChanged):
+        (WebCore::MediaSessionGLib::playbackStatusChanged):
+        (WebCore::MediaSessionGLib::getActiveSessionPosition):
+        * platform/audio/glib/MediaSessionGLib.h: Added.
+        (WebCore::MediaSessionGLib::manager const):
+        * platform/audio/glib/MediaSessionManagerGLib.cpp:
+        (WebCore::PlatformMediaSessionManager::create):
+        (WebCore::MediaSessionManagerGLib::MediaSessionManagerGLib):
+        (WebCore::MediaSessionManagerGLib::addSession):
+        (WebCore::MediaSessionManagerGLib::removeSession):
+        (WebCore::MediaSessionManagerGLib::sessionStateChanged):
+        (WebCore::MediaSessionManagerGLib::clientCharacteristicsChanged):
+        (WebCore::MediaSessionManagerGLib::updateNowPlayingInfo):
+        * platform/audio/glib/MediaSessionManagerGLib.h:
+        (WebCore::MediaSessionManagerGLib::mprisInterface const):
+
 2021-10-01  Nikos Mouchtaris  <[email protected]>
 
         Allow NaN, infinity, and -infinity in calc

Modified: trunk/Source/WebCore/platform/SourcesGLib.txt (283436 => 283437)


--- trunk/Source/WebCore/platform/SourcesGLib.txt	2021-10-02 09:04:16 UTC (rev 283436)
+++ trunk/Source/WebCore/platform/SourcesGLib.txt	2021-10-02 09:07:12 UTC (rev 283437)
@@ -22,6 +22,7 @@
 // THE POSSIBILITY OF SUCH DAMAGE.
 
 platform/audio/glib/AudioBusGLib.cpp
+platform/audio/glib/MediaSessionGLib.cpp
 platform/audio/glib/MediaSessionManagerGLib.cpp
 
 platform/glib/ApplicationGLib.cpp

Added: trunk/Source/WebCore/platform/audio/glib/MediaSessionGLib.cpp (0 => 283437)


--- trunk/Source/WebCore/platform/audio/glib/MediaSessionGLib.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/audio/glib/MediaSessionGLib.cpp	2021-10-02 09:07:12 UTC (rev 283437)
@@ -0,0 +1,379 @@
+/*
+ *  Copyright (C) 2021 Igalia S.L
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+#include "MediaSessionGLib.h"
+
+#if USE(GLIB) && ENABLE(MEDIA_SESSION)
+
+#include "ApplicationGLib.h"
+#include "MediaSessionManagerGLib.h"
+#include <gio/gio.h>
+#include <wtf/SortedArrayMap.h>
+
+namespace WebCore {
+
+#define DBUS_MPRIS_OBJECT_PATH "/org/mpris/MediaPlayer2"
+#define DBUS_MPRIS_PLAYER_INTERFACE "org.mpris.MediaPlayer2.Player"
+#define DBUS_MPRIS_TRACK_PATH "/org/mpris/MediaPlayer2/webkit"
+
+static std::optional<PlatformMediaSession::RemoteControlCommandType> getCommand(const char* name)
+{
+    static const std::pair<ComparableASCIILiteral, PlatformMediaSession::RemoteControlCommandType> commandList[] = {
+        { "Next", PlatformMediaSession::NextTrackCommand },
+        { "Pause", PlatformMediaSession::PauseCommand },
+        { "Play", PlatformMediaSession::PlayCommand },
+        { "PlayPause", PlatformMediaSession::TogglePlayPauseCommand },
+        { "Previous", PlatformMediaSession::PreviousTrackCommand },
+        { "Seek", PlatformMediaSession::SeekToPlaybackPositionCommand },
+        { "Stop", PlatformMediaSession::StopCommand }
+    };
+
+    static const SortedArrayMap map { commandList };
+    auto value = map.get(name, PlatformMediaSession::RemoteControlCommandType::NoCommand);
+    if (value == PlatformMediaSession::RemoteControlCommandType::NoCommand)
+        return { };
+    return value;
+}
+
+static void handleMethodCall(GDBusConnection* /* connection */, const char* /* sender */, const char* objectPath, const char* interfaceName, const char* methodName, GVariant* parameters, GDBusMethodInvocation* invocation, gpointer userData)
+{
+    ASSERT(isMainThread());
+    auto command = getCommand(methodName);
+    if (!command) {
+        g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "%s.%s.%s is not available now", objectPath, interfaceName, methodName);
+        return;
+    }
+    auto& session = *reinterpret_cast<MediaSessionGLib*>(userData);
+    auto& manager = session.manager();
+    PlatformMediaSession::RemoteCommandArgument argument;
+    if (*command == PlatformMediaSession::SeekToPlaybackPositionCommand) {
+        int64_t offset;
+        g_variant_get(parameters, "(x)", &offset);
+        argument.time = offset / 1000000;
+    }
+    manager.dispatch(*command, argument);
+    g_dbus_method_invocation_return_value(invocation, nullptr);
+}
+
+enum class MprisProperty : uint8_t {
+    NoProperty,
+    CanControl,
+    CanGoNext,
+    CanGoPrevious,
+    CanPause,
+    CanPlay,
+    CanQuit,
+    CanRaise,
+    CanSeek,
+    DesktopEntry,
+    GetMetadata,
+    GetPlaybackStatus,
+    GetPosition,
+    HasTrackList,
+    Identity,
+    SupportedMimeTypes,
+    SupportedUriSchemes,
+};
+
+static std::optional<MprisProperty> getMprisProperty(const char* propertyName)
+{
+    static constexpr std::pair<ComparableASCIILiteral, MprisProperty> propertiesList[] {
+        { "CanControl", MprisProperty::CanControl },
+        { "CanGoNext", MprisProperty::CanGoNext },
+        { "CanGoPrevious", MprisProperty::CanGoPrevious },
+        { "CanPause", MprisProperty::CanPause },
+        { "CanPlay", MprisProperty::CanPlay },
+        { "CanQuit", MprisProperty::CanQuit },
+        { "CanRaise", MprisProperty::CanRaise },
+        { "CanSeek", MprisProperty::CanSeek },
+        { "DesktopEntry", MprisProperty::DesktopEntry },
+        { "HasTrackList", MprisProperty::HasTrackList },
+        { "Identity", MprisProperty::Identity },
+        { "Metadata", MprisProperty::GetMetadata },
+        { "PlaybackStatus", MprisProperty::GetPlaybackStatus },
+        { "Position", MprisProperty::GetPosition },
+        { "SupportedMimeTypes", MprisProperty::SupportedMimeTypes },
+        { "SupportedUriSchemes", MprisProperty::SupportedUriSchemes }
+    };
+    static constexpr SortedArrayMap map { propertiesList };
+    auto value = map.get(propertyName, MprisProperty::NoProperty);
+    if (value == MprisProperty::NoProperty)
+        return { };
+    return value;
+}
+
+static GVariant* handleGetProperty(GDBusConnection*, const char* /* sender */, const char* objectPath, const char* interfaceName, const char* propertyName, GError** error, gpointer userData)
+{
+    ASSERT(isMainThread());
+    auto property = getMprisProperty(propertyName);
+    if (!property) {
+        g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "%s.%s %s is not supported", objectPath, interfaceName, propertyName);
+        return nullptr;
+    }
+
+    auto& session = *reinterpret_cast<MediaSessionGLib*>(userData);
+    switch (property.value()) {
+    case MprisProperty::NoProperty:
+        break;
+    case MprisProperty::SupportedUriSchemes:
+    case MprisProperty::SupportedMimeTypes:
+        return g_variant_new_strv(nullptr, 0);
+    case MprisProperty::GetPlaybackStatus:
+        return session.getPlaybackStatusAsGVariant({ });
+    case MprisProperty::GetMetadata:
+        return session.getMetadataAsGVariant({ });
+    case MprisProperty::GetPosition:
+        return session.getPositionAsGVariant();
+    case MprisProperty::Identity:
+        return g_variant_new_string(getApplicationName());
+    case MprisProperty::DesktopEntry:
+        return g_variant_new_string("");
+    case MprisProperty::CanSeek:
+        return session.canSeekAsGVariant();
+    case MprisProperty::HasTrackList:
+    case MprisProperty::CanQuit:
+    case MprisProperty::CanRaise:
+        return g_variant_new_boolean(false);
+    case MprisProperty::CanControl:
+    case MprisProperty::CanGoNext:
+    case MprisProperty::CanGoPrevious:
+    case MprisProperty::CanPlay:
+    case MprisProperty::CanPause:
+        return g_variant_new_boolean(true);
+    }
+
+    return nullptr;
+}
+
+static gboolean handleSetProperty(GDBusConnection*, const char* /* sender */, const char* /* objectPath */, const char* interfaceName, const char* propertyName, GVariant*, GError** error, gpointer)
+{
+    ASSERT(isMainThread());
+    g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED, "%s:%s setting is not supported", interfaceName, propertyName);
+    return FALSE;
+}
+
+static const GDBusInterfaceVTable gInterfaceVTable = {
+    handleMethodCall, handleGetProperty, handleSetProperty, { nullptr }
+};
+
+std::unique_ptr<MediaSessionGLib> MediaSessionGLib::create(MediaSessionManagerGLib& manager, MediaSessionIdentifier identifier)
+{
+    GUniqueOutPtr<GError> error;
+    GUniquePtr<char> address(g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SESSION, nullptr, &error.outPtr()));
+    if (error) {
+        g_warning("Unable to get session D-Bus address: %s", error->message);
+        return nullptr;
+    }
+    auto connection = adoptGRef(reinterpret_cast<GDBusConnection*>(g_object_new(G_TYPE_DBUS_CONNECTION,
+        "address", address.get(),
+        "flags", G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
+        "exit-on-close", TRUE, nullptr)));
+    g_initable_init(G_INITABLE(connection.get()), nullptr, &error.outPtr());
+    if (error) {
+        g_warning("Unable to connect to D-Bus session bus: %s", error->message);
+        return nullptr;
+    }
+    return makeUnique<MediaSessionGLib>(manager, WTFMove(connection), identifier);
+}
+
+MediaSessionGLib::MediaSessionGLib(MediaSessionManagerGLib& manager, GRefPtr<GDBusConnection>&& connection, MediaSessionIdentifier identifier)
+    : m_identifier(identifier)
+    , m_manager(manager)
+    , m_connection(WTFMove(connection))
+{
+    const auto& mprisInterface = m_manager.mprisInterface();
+    GUniqueOutPtr<GError> error;
+    m_rootRegistrationId = g_dbus_connection_register_object(m_connection.get(), DBUS_MPRIS_OBJECT_PATH, mprisInterface->interfaces[0],
+        &gInterfaceVTable, this, nullptr, &error.outPtr());
+
+    if (!m_rootRegistrationId) {
+        g_warning("Failed to register MPRIS D-Bus object: %s", error->message);
+        return;
+    }
+
+    m_playerRegistrationId = g_dbus_connection_register_object(m_connection.get(), DBUS_MPRIS_OBJECT_PATH, mprisInterface->interfaces[1],
+        &gInterfaceVTable, this, nullptr, &error.outPtr());
+
+    if (!m_playerRegistrationId) {
+        g_warning("Failed at MPRIS object registration: %s", error->message);
+        return;
+    }
+
+    const auto& applicationID = getApplicationID();
+    m_instanceId = applicationID.isEmpty() ? makeString("org.mpris.MediaPlayer2.webkit.instance", getpid(), "-", identifier.toUInt64()) : makeString("org.mpris.MediaPlayer2.", applicationID.ascii().data(), "-", identifier.toUInt64());
+
+    m_ownerId = g_bus_own_name_on_connection(m_connection.get(), m_instanceId.ascii().data(), G_BUS_NAME_OWNER_FLAGS_NONE, nullptr,
+        reinterpret_cast<GBusNameLostCallback>(+[](GDBusConnection* connection, const char*, gpointer userData) {
+            auto& session = *reinterpret_cast<MediaSessionGLib*>(userData);
+            session.nameLost(connection);
+        }), this, nullptr);
+}
+
+MediaSessionGLib::~MediaSessionGLib()
+{
+    if (m_ownerId)
+        g_bus_unown_name(m_ownerId);
+}
+
+void MediaSessionGLib::nameLost(GDBusConnection* connection)
+{
+    if (UNLIKELY(!m_connection)) {
+        g_warning("Unable to acquire MPRIS D-Bus session ownership for name %s", m_instanceId.ascii().data());
+        return;
+    }
+
+    m_connection = nullptr;
+    if (!m_rootRegistrationId)
+        return;
+
+    if (g_dbus_connection_unregister_object(connection, m_rootRegistrationId))
+        m_rootRegistrationId = 0;
+    else
+        g_warning("Unable to unregister MPRIS D-Bus object.");
+
+    if (!m_playerRegistrationId)
+        return;
+
+    if (g_dbus_connection_unregister_object(connection, m_playerRegistrationId))
+        m_playerRegistrationId = 0;
+    else
+        g_warning("Unable to unregister MPRIS D-Bus player object.");
+}
+
+void MediaSessionGLib::emitPositionChanged(double time)
+{
+    GUniqueOutPtr<GError> error;
+    int64_t position = time * 1000000;
+    if (!g_dbus_connection_emit_signal(m_connection.get(), nullptr, DBUS_MPRIS_OBJECT_PATH, DBUS_MPRIS_PLAYER_INTERFACE, "Seeked", g_variant_new("(x)", position), &error.outPtr()))
+        g_warning("Failed to emit MPRIS Seeked signal: %s", error->message);
+}
+
+void MediaSessionGLib::updateNowPlaying(NowPlayingInfo& nowPlayingInfo)
+{
+    GVariantBuilder propertiesBuilder;
+    g_variant_builder_init(&propertiesBuilder, G_VARIANT_TYPE("a{sv}"));
+    g_variant_builder_add(&propertiesBuilder, "{sv}", "Metadata", getMetadataAsGVariant(nowPlayingInfo));
+    emitPropertiesChanged(g_variant_new("(sa{sv}as)", DBUS_MPRIS_PLAYER_INTERFACE, &propertiesBuilder, nullptr));
+    g_variant_builder_clear(&propertiesBuilder);
+}
+
+GVariant* MediaSessionGLib::getMetadataAsGVariant(std::optional<NowPlayingInfo> info)
+{
+    if (!info)
+        info = nowPlayingInfo();
+
+    GVariantBuilder builder;
+    g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
+
+    if (!info)
+        return g_variant_builder_end(&builder);
+
+    g_variant_builder_add(&builder, "{sv}", "mpris:trackid", g_variant_new("o", DBUS_MPRIS_TRACK_PATH));
+    g_variant_builder_add(&builder, "{sv}", "mpris:length", g_variant_new_int64(info->duration * 1000000));
+    g_variant_builder_add(&builder, "{sv}", "xesam:title", g_variant_new_string(info->title.utf8().data()));
+    g_variant_builder_add(&builder, "{sv}", "xesam:album", g_variant_new_string(info->album.utf8().data()));
+    if (info->artwork)
+        g_variant_builder_add(&builder, "{sv}", "mpris:artUrl", g_variant_new_string(info->artwork->src.utf8().data()));
+
+    GVariantBuilder artistBuilder;
+    g_variant_builder_init(&artistBuilder, G_VARIANT_TYPE("as"));
+    g_variant_builder_add(&artistBuilder, "s", info->artist.utf8().data());
+    g_variant_builder_add(&builder, "{sv}", "xesam:artist", g_variant_builder_end(&artistBuilder));
+
+    return g_variant_builder_end(&builder);
+}
+
+GVariant* MediaSessionGLib::getPlaybackStatusAsGVariant(std::optional<const PlatformMediaSession*> session)
+{
+    auto state = [this, session = WTFMove(session)]() -> PlatformMediaSession::State {
+        if (session)
+            return session.value()->state();
+
+        auto* nowPlayingSession = m_manager.nowPlayingEligibleSession();
+        if (nowPlayingSession)
+            return nowPlayingSession->state();
+
+        return PlatformMediaSession::State::Idle;
+    }();
+
+    switch (state) {
+    case PlatformMediaSession::State::Autoplaying:
+    case PlatformMediaSession::State::Playing:
+        return g_variant_new_string("Playing");
+    case PlatformMediaSession::State::Paused:
+        return g_variant_new_string("Paused");
+    case PlatformMediaSession::State::Idle:
+    case PlatformMediaSession::State::Interrupted:
+        return g_variant_new_string("Stopped");
+    }
+    ASSERT_NOT_REACHED();
+    return nullptr;
+}
+
+void MediaSessionGLib::emitPropertiesChanged(GVariant* parameters)
+{
+    if (!m_connection)
+        return;
+
+    GUniqueOutPtr<GError> error;
+    if (!g_dbus_connection_emit_signal(m_connection.get(), nullptr, DBUS_MPRIS_OBJECT_PATH, "org.freedesktop.DBus.Properties", "PropertiesChanged", parameters, &error.outPtr()))
+        g_warning("Failed to emit MPRIS properties changed: %s", error->message);
+}
+
+void MediaSessionGLib::playbackStatusChanged(PlatformMediaSession& platformSession)
+{
+    GVariantBuilder builder;
+    g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
+    g_variant_builder_add(&builder, "{sv}", "PlaybackStatus", getPlaybackStatusAsGVariant(&platformSession));
+    emitPropertiesChanged(g_variant_new("(sa{sv}as)", DBUS_MPRIS_PLAYER_INTERFACE, &builder, nullptr));
+    g_variant_builder_clear(&builder);
+}
+
+std::optional<NowPlayingInfo> MediaSessionGLib::nowPlayingInfo()
+{
+    std::optional<NowPlayingInfo> nowPlayingInfo;
+    m_manager.forEachMatchingSession([&](auto& session) {
+        return session.mediaSessionIdentifier() == m_identifier;
+    }, [&](auto& session) {
+        nowPlayingInfo = session.nowPlayingInfo();
+    });
+    return nowPlayingInfo;
+}
+
+GVariant* MediaSessionGLib::getPositionAsGVariant()
+{
+    auto info = nowPlayingInfo();
+    return g_variant_new_int64(info ? info->currentTime * 1000000 : 0);
+}
+
+GVariant* MediaSessionGLib::canSeekAsGVariant()
+{
+    bool canSeek = false;
+    m_manager.forEachMatchingSession([&](auto& session) {
+        return session.mediaSessionIdentifier() == m_identifier;
+    }, [&](auto& session) {
+        canSeek = session.supportsSeeking();
+    });
+
+    return g_variant_new_boolean(canSeek);
+}
+
+} // namespace WebCore
+
+#endif // USE(GLIB) && ENABLE(MEDIA_SESSION)

Added: trunk/Source/WebCore/platform/audio/glib/MediaSessionGLib.h (0 => 283437)


--- trunk/Source/WebCore/platform/audio/glib/MediaSessionGLib.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/audio/glib/MediaSessionGLib.h	2021-10-02 09:07:12 UTC (rev 283437)
@@ -0,0 +1,67 @@
+/*
+ *  Copyright (C) 2021 Igalia S.L
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#pragma once
+
+#if USE(GLIB) && ENABLE(MEDIA_SESSION)
+
+#include "MediaSessionIdentifier.h"
+#include "PlatformMediaSession.h"
+#include <wtf/glib/GRefPtr.h>
+
+namespace WebCore {
+
+class MediaSessionManagerGLib;
+
+class MediaSessionGLib {
+    WTF_MAKE_FAST_ALLOCATED;
+
+public:
+    static std::unique_ptr<MediaSessionGLib> create(MediaSessionManagerGLib&, MediaSessionIdentifier);
+
+    explicit MediaSessionGLib(MediaSessionManagerGLib&, GRefPtr<GDBusConnection>&&, MediaSessionIdentifier);
+    ~MediaSessionGLib();
+
+    MediaSessionManagerGLib& manager() const { return m_manager; }
+
+    GVariant* getPlaybackStatusAsGVariant(std::optional<const PlatformMediaSession*>);
+    GVariant* getMetadataAsGVariant(std::optional<NowPlayingInfo>);
+    GVariant* getPositionAsGVariant();
+    GVariant* canSeekAsGVariant();
+
+    void nameLost(GDBusConnection*);
+    void emitPositionChanged(double time);
+    void updateNowPlaying(NowPlayingInfo&);
+    void playbackStatusChanged(PlatformMediaSession&);
+
+private:
+    void emitPropertiesChanged(GVariant*);
+    std::optional<NowPlayingInfo> nowPlayingInfo();
+
+    MediaSessionIdentifier m_identifier;
+    MediaSessionManagerGLib& m_manager;
+    GRefPtr<GDBusConnection> m_connection;
+    String m_instanceId;
+    unsigned m_ownerId { 0 };
+    unsigned m_rootRegistrationId { 0 };
+    unsigned m_playerRegistrationId { 0 };
+};
+
+} // namespace WebCore
+
+#endif // USE(GLIB) && ENABLE(MEDIA_SESSION)

Modified: trunk/Source/WebCore/platform/audio/glib/MediaSessionManagerGLib.cpp (283436 => 283437)


--- trunk/Source/WebCore/platform/audio/glib/MediaSessionManagerGLib.cpp	2021-10-02 09:04:16 UTC (rev 283436)
+++ trunk/Source/WebCore/platform/audio/glib/MediaSessionManagerGLib.cpp	2021-10-02 09:07:12 UTC (rev 283437)
@@ -21,7 +21,6 @@
 
 #if USE(GLIB) && ENABLE(MEDIA_SESSION)
 
-#include "ApplicationGLib.h"
 #include "AudioSession.h"
 #include "HTMLMediaElement.h"
 #include "MediaPlayer.h"
@@ -31,7 +30,6 @@
 #include "PlatformStrategies.h"
 
 #include <gio/gio.h>
-#include <wtf/SortedArrayMap.h>
 
 // https://specifications.freedesktop.org/mpris-spec/latest/
 static const char s_mprisInterface[] =
@@ -110,245 +108,27 @@
         "</interface>"
     "</node>";
 
-#define DBUS_MPRIS_OBJECT_PATH "/org/mpris/MediaPlayer2"
-#define DBUS_MPRIS_PLAYER_INTERFACE "org.mpris.MediaPlayer2.Player"
-#define DBUS_MPRIS_TRACK_PATH "/org/mpris/MediaPlayer2/webkit"
-
 namespace WebCore {
 
 std::unique_ptr<PlatformMediaSessionManager> PlatformMediaSessionManager::create()
 {
-    return makeUnique<MediaSessionManagerGLib>();
-}
-
-MediaSessionManagerGLib::MediaSessionManagerGLib()
-    : m_nowPlayingManager(platformStrategies()->mediaStrategy().createNowPlayingManager())
-{
-}
-
-MediaSessionManagerGLib::~MediaSessionManagerGLib()
-{
-    if (m_ownerId)
-        g_bus_unown_name(m_ownerId);
-}
-
-static std::optional<PlatformMediaSession::RemoteControlCommandType> getCommand(const char* name)
-{
-    static const std::pair<ComparableASCIILiteral, PlatformMediaSession::RemoteControlCommandType> commandList[] = {
-        { "Next", PlatformMediaSession::NextTrackCommand },
-        { "Pause", PlatformMediaSession::PauseCommand },
-        { "Play", PlatformMediaSession::PlayCommand },
-        { "PlayPause", PlatformMediaSession::TogglePlayPauseCommand },
-        { "Previous", PlatformMediaSession::PreviousTrackCommand },
-        { "Seek", PlatformMediaSession::SeekToPlaybackPositionCommand },
-        { "Stop", PlatformMediaSession::StopCommand }
-    };
-
-    static const SortedArrayMap map { commandList };
-    auto value = map.get(name, PlatformMediaSession::RemoteControlCommandType::NoCommand);
-    if (value == PlatformMediaSession::RemoteControlCommandType::NoCommand)
-        return { };
-    return value;
-}
-
-static void handleMethodCall(GDBusConnection* /* connection */, const char* /* sender */, const char* objectPath, const char* interfaceName, const char* methodName, GVariant* parameters, GDBusMethodInvocation* invocation, gpointer userData)
-{
-    ASSERT(isMainThread());
-    auto command = getCommand(methodName);
-    if (!command) {
-        g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "%s.%s.%s is not available now", objectPath, interfaceName, methodName);
-        return;
-    }
-    auto& manager = *reinterpret_cast<MediaSessionManagerGLib*>(userData);
-    PlatformMediaSession::RemoteCommandArgument argument;
-    if (*command == PlatformMediaSession::SeekToPlaybackPositionCommand) {
-        int64_t offset;
-        g_variant_get(parameters, "(x)", &offset);
-        argument.time = offset / 1000000;
-    }
-    manager.dispatch(*command, argument);
-    g_dbus_method_invocation_return_value(invocation, nullptr);
-}
-
-enum class MprisProperty : uint8_t {
-    NoProperty,
-    CanControl,
-    CanGoNext,
-    CanGoPrevious,
-    CanPause,
-    CanPlay,
-    CanQuit,
-    CanRaise,
-    CanSeek,
-    DesktopEntry,
-    GetMetadata,
-    GetPlaybackStatus,
-    GetPosition,
-    HasTrackList,
-    Identity,
-    SupportedMimeTypes,
-    SupportedUriSchemes,
-};
-
-static std::optional<MprisProperty> getMprisProperty(const char* propertyName)
-{
-    static constexpr std::pair<ComparableASCIILiteral, MprisProperty> propertiesList[] {
-        { "CanControl", MprisProperty::CanControl },
-        { "CanGoNext", MprisProperty::CanGoNext },
-        { "CanGoPrevious", MprisProperty::CanGoPrevious },
-        { "CanPause", MprisProperty::CanPause },
-        { "CanPlay", MprisProperty::CanPlay },
-        { "CanQuit", MprisProperty::CanQuit },
-        { "CanRaise", MprisProperty::CanRaise },
-        { "CanSeek", MprisProperty::CanSeek },
-        { "DesktopEntry", MprisProperty::DesktopEntry },
-        { "HasTrackList", MprisProperty::HasTrackList },
-        { "Identity", MprisProperty::Identity },
-        { "Metadata", MprisProperty::GetMetadata },
-        { "PlaybackStatus", MprisProperty::GetPlaybackStatus },
-        { "Position", MprisProperty::GetPosition },
-        { "SupportedMimeTypes", MprisProperty::SupportedMimeTypes },
-        { "SupportedUriSchemes", MprisProperty::SupportedUriSchemes }
-    };
-    static constexpr SortedArrayMap map { propertiesList };
-    auto value = map.get(propertyName, MprisProperty::NoProperty);
-    if (value == MprisProperty::NoProperty)
-        return { };
-    return value;
-}
-
-static GVariant* handleGetProperty(GDBusConnection*, const char* /* sender */, const char* objectPath, const char* interfaceName, const char* propertyName, GError** error, gpointer userData)
-{
-    ASSERT(isMainThread());
-    auto property = getMprisProperty(propertyName);
-    if (!property) {
-        g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "%s.%s %s is not supported", objectPath, interfaceName, propertyName);
-        return nullptr;
-    }
-
-    auto& manager = *reinterpret_cast<MediaSessionManagerGLib*>(userData);
-    switch (property.value()) {
-    case MprisProperty::NoProperty:
-        break;
-    case MprisProperty::SupportedUriSchemes:
-    case MprisProperty::SupportedMimeTypes:
-        return g_variant_new_strv(nullptr, 0);
-    case MprisProperty::GetPlaybackStatus:
-        return manager.getPlaybackStatusAsGVariant({ });
-    case MprisProperty::GetMetadata: {
-        auto* variant = manager.getMetadataAsGVariant();
-        if (!variant)
-            return nullptr;
-        return g_variant_ref(variant);
-    }
-    case MprisProperty::GetPosition:
-        return manager.getActiveSessionPosition();
-    case MprisProperty::Identity:
-        return g_variant_new_string(getApplicationName());
-    case MprisProperty::DesktopEntry:
-        return g_variant_new_string("");
-    case MprisProperty::HasTrackList:
-    case MprisProperty::CanQuit:
-    case MprisProperty::CanRaise:
-        return g_variant_new_boolean(false);
-    case MprisProperty::CanSeek:
-    case MprisProperty::CanControl:
-    case MprisProperty::CanGoNext:
-    case MprisProperty::CanGoPrevious:
-    case MprisProperty::CanPlay:
-    case MprisProperty::CanPause:
-        return g_variant_new_boolean(true);
-    }
-
-    return nullptr;
-}
-
-static gboolean handleSetProperty(GDBusConnection*, const char* /* sender */, const char* /* objectPath */, const char* interfaceName, const char* propertyName, GVariant*, GError** error, gpointer)
-{
-    ASSERT(isMainThread());
-    g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED, "%s:%s setting is not supported", interfaceName, propertyName);
-    return FALSE;
-}
-
-static const GDBusInterfaceVTable gInterfaceVTable = {
-    handleMethodCall, handleGetProperty, handleSetProperty, { nullptr }
-};
-
-bool MediaSessionManagerGLib::setupMpris()
-{
-    if (m_ownerId)
-        return true;
-
-    const auto& applicationID = getApplicationID();
-    m_instanceId = applicationID.isEmpty() ? makeString("org.mpris.MediaPlayer2.webkit.instance", getpid()) : makeString("org.mpris.MediaPlayer2.", applicationID.ascii().data());
-
-    m_ownerId = g_bus_own_name(G_BUS_TYPE_SESSION, m_instanceId.ascii().data(),
-        G_BUS_NAME_OWNER_FLAGS_NONE, reinterpret_cast<GBusAcquiredCallback>(+[](GDBusConnection* connection, const gchar*, gpointer userData) {
-            auto& manager = *reinterpret_cast<MediaSessionManagerGLib*>(userData);
-            manager.busAcquired(connection);
-        }),
-        reinterpret_cast<GBusNameAcquiredCallback>(+[](GDBusConnection* connection, const char*, gpointer userData) {
-            auto& manager = *reinterpret_cast<MediaSessionManagerGLib*>(userData);
-            manager.nameAcquired(connection);
-        }),
-        reinterpret_cast<GBusNameLostCallback>(+[](GDBusConnection* connection, const char*, gpointer userData) {
-            auto& manager = *reinterpret_cast<MediaSessionManagerGLib*>(userData);
-            manager.nameLost(connection);
-        }), this, nullptr);
-
     GUniqueOutPtr<GError> error;
-    m_mprisInterface = adoptGRef(g_dbus_node_info_new_for_xml(s_mprisInterface, &error.outPtr()));
-    if (!m_mprisInterface) {
+    auto mprisInterface = adoptGRef(g_dbus_node_info_new_for_xml(s_mprisInterface, &error.outPtr()));
+    if (!mprisInterface) {
         g_warning("Failed at parsing XML Interface definition: %s", error->message);
-        return false;
+        return nullptr;
     }
-
-    return true;
+    return makeUnique<MediaSessionManagerGLib>(WTFMove(mprisInterface));
 }
 
-void MediaSessionManagerGLib::busAcquired(GDBusConnection* connection)
+MediaSessionManagerGLib::MediaSessionManagerGLib(GRefPtr<GDBusNodeInfo>&& mprisInterface)
+    : m_mprisInterface(WTFMove(mprisInterface))
+    , m_nowPlayingManager(platformStrategies()->mediaStrategy().createNowPlayingManager())
 {
-    GUniqueOutPtr<GError> error;
-    m_rootRegistrationId = g_dbus_connection_register_object(connection, DBUS_MPRIS_OBJECT_PATH, m_mprisInterface->interfaces[0],
-        &gInterfaceVTable, this, nullptr, &error.outPtr());
-
-    if (!m_rootRegistrationId) {
-        g_warning("Failed to register MPRIS D-Bus object: %s", error->message);
-        return;
-    }
-
-    m_playerRegistrationId = g_dbus_connection_register_object(connection, DBUS_MPRIS_OBJECT_PATH, m_mprisInterface->interfaces[1],
-        &gInterfaceVTable, this, nullptr, &error.outPtr());
-
-    if (!m_playerRegistrationId)
-        g_warning("Failed at MPRIS object registration: %s", error->message);
 }
 
-void MediaSessionManagerGLib::nameLost(GDBusConnection* connection)
-{
-    if (UNLIKELY(!m_connection)) {
-        g_warning("Unable to acquire MPRIS D-Bus session ownership for name %s", m_instanceId.ascii().data());
-        return;
-    }
+MediaSessionManagerGLib::~MediaSessionManagerGLib() = default;
 
-    m_connection = nullptr;
-    if (!m_rootRegistrationId)
-        return;
-
-    if (g_dbus_connection_unregister_object(connection, m_rootRegistrationId))
-        m_rootRegistrationId = 0;
-    else
-        g_warning("Unable to unregister MPRIS D-Bus object.");
-
-    if (!m_playerRegistrationId)
-        return;
-
-    if (g_dbus_connection_unregister_object(connection, m_playerRegistrationId))
-        m_playerRegistrationId = 0;
-    else
-        g_warning("Unable to unregister MPRIS D-Bus player object.");
-}
-
 void MediaSessionManagerGLib::beginInterruption(PlatformMediaSession::InterruptionType type)
 {
     if (type == PlatformMediaSession::InterruptionType::SystemInterruption) {
@@ -386,14 +166,17 @@
     scheduleSessionStatusUpdate();
 }
 
-void MediaSessionManagerGLib::addSession(PlatformMediaSession& session)
+void MediaSessionManagerGLib::addSession(PlatformMediaSession& platformSession)
 {
-    if (!setupMpris())
+    auto identifier = platformSession.mediaSessionIdentifier();
+    auto session = MediaSessionGLib::create(*this, identifier);
+    if (!session)
         return;
 
+    m_sessions.add(identifier, WTFMove(session));
     m_nowPlayingManager->addClient(*this);
 
-    PlatformMediaSessionManager::addSession(session);
+    PlatformMediaSessionManager::addSession(platformSession);
 }
 
 void MediaSessionManagerGLib::removeSession(PlatformMediaSession& session)
@@ -400,12 +183,10 @@
 {
     PlatformMediaSessionManager::removeSession(session);
 
-    if (hasNoSession()) {
+    m_sessions.remove(session.mediaSessionIdentifier());
+    if (hasNoSession())
         m_nowPlayingManager->removeClient(*this);
-        if (m_ownerId)
-            g_bus_unown_name(m_ownerId);
-        m_ownerId = 0;
-    }
+
     scheduleSessionStatusUpdate();
 }
 
@@ -434,26 +215,24 @@
     }
 }
 
-void MediaSessionManagerGLib::sessionStateChanged(PlatformMediaSession& session)
+void MediaSessionManagerGLib::sessionStateChanged(PlatformMediaSession& platformSession)
 {
-    PlatformMediaSessionManager::sessionStateChanged(session);
+    PlatformMediaSessionManager::sessionStateChanged(platformSession);
 
-    GVariantBuilder builder;
-    g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
-    g_variant_builder_add(&builder, "{sv}", "PlaybackStatus", getPlaybackStatusAsGVariant(&session));
-    emitPropertiesChanged(g_variant_new("(sa{sv}as)", DBUS_MPRIS_PLAYER_INTERFACE, &builder, nullptr));
-    g_variant_builder_clear(&builder);
+    auto session = m_sessions.get(platformSession.mediaSessionIdentifier());
+    if (!session)
+        return;
+
+    session->playbackStatusChanged(platformSession);
 }
 
-void MediaSessionManagerGLib::clientCharacteristicsChanged(PlatformMediaSession& session)
+void MediaSessionManagerGLib::clientCharacteristicsChanged(PlatformMediaSession& platformSession)
 {
-    ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier());
+    ALWAYS_LOG(LOGIDENTIFIER, platformSession.logIdentifier());
     if (m_isSeeking) {
         m_isSeeking = false;
-        GUniqueOutPtr<GError> error;
-        int64_t position = session.nowPlayingInfo()->currentTime * 1000000;
-        if (!g_dbus_connection_emit_signal(m_connection.get(), nullptr, DBUS_MPRIS_OBJECT_PATH, DBUS_MPRIS_PLAYER_INTERFACE, "Seeked", g_variant_new("(x)", position), &error.outPtr()))
-            g_warning("Failed to emit MPRIS Seeked signal: %s", error->message);
+        auto session = m_sessions.get(platformSession.mediaSessionIdentifier());
+        session->emitPositionChanged(platformSession.nowPlayingInfo()->currentTime);
     }
     scheduleSessionStatusUpdate();
 }
@@ -491,11 +270,8 @@
 
 void MediaSessionManagerGLib::updateNowPlayingInfo()
 {
-    std::optional<NowPlayingInfo> nowPlayingInfo;
-    if (auto* session = nowPlayingEligibleSession())
-        nowPlayingInfo = session->nowPlayingInfo();
-
-    if (!nowPlayingInfo) {
+    auto* platformSession = nowPlayingEligibleSession();
+    if (!platformSession) {
         if (m_registeredAsNowPlayingApplication) {
             ALWAYS_LOG(LOGIDENTIFIER, "clearing now playing info");
             m_nowPlayingManager->clearNowPlayingInfo();
@@ -507,10 +283,13 @@
         m_lastUpdatedNowPlayingDuration = NAN;
         m_lastUpdatedNowPlayingElapsedTime = NAN;
         m_lastUpdatedNowPlayingInfoUniqueIdentifier = { };
-        m_nowPlayingInfo.clear();
         return;
     }
 
+    auto nowPlayingInfo = platformSession->nowPlayingInfo();
+    if (!nowPlayingInfo)
+        return;
+
     m_haveEverRegisteredAsNowPlayingApplication = true;
 
     if (m_nowPlayingManager->setNowPlayingInfo(*nowPlayingInfo))
@@ -536,62 +315,10 @@
 
     m_nowPlayingActive = nowPlayingInfo->allowsNowPlayingControlsVisibility;
 
-    GVariantBuilder builder;
-    g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
-    g_variant_builder_add(&builder, "{sv}", "mpris:trackid", g_variant_new("o", DBUS_MPRIS_TRACK_PATH));
-    g_variant_builder_add(&builder, "{sv}", "mpris:length", g_variant_new_int64(nowPlayingInfo->duration * 1000000));
-    g_variant_builder_add(&builder, "{sv}", "xesam:title", g_variant_new_string(nowPlayingInfo->title.utf8().data()));
-    g_variant_builder_add(&builder, "{sv}", "xesam:album", g_variant_new_string(nowPlayingInfo->album.utf8().data()));
-    if (nowPlayingInfo->artwork)
-        g_variant_builder_add(&builder, "{sv}", "mpris:artUrl", g_variant_new_string(nowPlayingInfo->artwork->src.utf8().data()));
-
-    GVariantBuilder artistBuilder;
-    g_variant_builder_init(&artistBuilder, G_VARIANT_TYPE("as"));
-    g_variant_builder_add(&artistBuilder, "s", nowPlayingInfo->artist.utf8().data());
-    g_variant_builder_add(&builder, "{sv}", "xesam:artist", g_variant_builder_end(&artistBuilder));
-
-    m_nowPlayingInfo = g_variant_builder_end(&builder);
-
-    GVariantBuilder propertiesBuilder;
-    g_variant_builder_init(&propertiesBuilder, G_VARIANT_TYPE("a{sv}"));
-    g_variant_builder_add(&propertiesBuilder, "{sv}", "Metadata", m_nowPlayingInfo.get());
-    emitPropertiesChanged(g_variant_new("(sa{sv}as)", DBUS_MPRIS_PLAYER_INTERFACE, &propertiesBuilder, nullptr));
-    g_variant_builder_clear(&propertiesBuilder);
+    auto session = m_sessions.get(platformSession->mediaSessionIdentifier());
+    session->updateNowPlaying(*nowPlayingInfo);
 }
 
-GVariant* MediaSessionManagerGLib::getPlaybackStatusAsGVariant(std::optional<const PlatformMediaSession*> session)
-{
-    auto state = [this, session = WTFMove(session)]() -> PlatformMediaSession::State {
-        if (session)
-            return session.value()->state();
-
-        auto* nowPlayingSession = nowPlayingEligibleSession();
-        if (nowPlayingSession)
-            return nowPlayingSession->state();
-
-        return PlatformMediaSession::State::Idle;
-    }();
-
-    switch (state) {
-    case PlatformMediaSession::State::Autoplaying:
-    case PlatformMediaSession::State::Playing:
-        return g_variant_new_string("Playing");
-    case PlatformMediaSession::State::Paused:
-        return g_variant_new_string("Paused");
-    case PlatformMediaSession::State::Idle:
-    case PlatformMediaSession::State::Interrupted:
-        return g_variant_new_string("Stopped");
-    }
-    ASSERT_NOT_REACHED();
-    return nullptr;
-}
-
-GVariant* MediaSessionManagerGLib::getActiveSessionPosition()
-{
-    auto* session = nowPlayingEligibleSession();
-    return g_variant_new_int64(session ? session->nowPlayingInfo()->currentTime * 1000000 : 0);
-}
-
 void MediaSessionManagerGLib::dispatch(PlatformMediaSession::RemoteControlCommandType platformCommand, PlatformMediaSession::RemoteCommandArgument argument)
 {
     m_isSeeking = platformCommand == PlatformMediaSession::SeekToPlaybackPositionCommand;
@@ -598,16 +325,6 @@
     m_nowPlayingManager->didReceiveRemoteControlCommand(platformCommand, argument);
 }
 
-void MediaSessionManagerGLib::emitPropertiesChanged(GVariant* parameters)
-{
-    if (!m_connection)
-        return;
-
-    GUniqueOutPtr<GError> error;
-    if (!g_dbus_connection_emit_signal(m_connection.get(), nullptr, DBUS_MPRIS_OBJECT_PATH, "org.freedesktop.DBus.Properties", "PropertiesChanged", parameters, &error.outPtr()))
-        g_warning("Failed to emit MPRIS properties changed: %s", error->message);
-}
-
 } // namespace WebCore
 
-#endif // USE(GLIB)
+#endif // USE(GLIB) && ENABLE(MEDIA_SESSION)

Modified: trunk/Source/WebCore/platform/audio/glib/MediaSessionManagerGLib.h (283436 => 283437)


--- trunk/Source/WebCore/platform/audio/glib/MediaSessionManagerGLib.h	2021-10-02 09:04:16 UTC (rev 283436)
+++ trunk/Source/WebCore/platform/audio/glib/MediaSessionManagerGLib.h	2021-10-02 09:07:12 UTC (rev 283437)
@@ -20,6 +20,7 @@
 
 #if USE(GLIB) && ENABLE(MEDIA_SESSION)
 
+#include "MediaSessionIdentifier.h"
 #include "NowPlayingManager.h"
 #include "PlatformMediaSessionManager.h"
 #include <wtf/glib/GRefPtr.h>
@@ -27,6 +28,7 @@
 namespace WebCore {
 
 struct NowPlayingInfo;
+class MediaSessionGLib;
 
 class MediaSessionManagerGLib
     : public PlatformMediaSessionManager
@@ -33,11 +35,9 @@
     , private NowPlayingManager::Client {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    MediaSessionManagerGLib();
+    MediaSessionManagerGLib(GRefPtr<GDBusNodeInfo>&&);
     ~MediaSessionManagerGLib();
 
-    bool setupMpris();
-
     void beginInterruption(PlatformMediaSession::InterruptionType) final;
 
     bool hasActiveNowPlayingSession() const final { return m_nowPlayingActive; }
@@ -48,14 +48,11 @@
     bool registeredAsNowPlayingApplication() const final { return m_registeredAsNowPlayingApplication; }
     bool haveEverRegisteredAsNowPlayingApplication() const final { return m_haveEverRegisteredAsNowPlayingApplication; }
 
-    void busAcquired(GDBusConnection*);
-    void nameAcquired(GDBusConnection* connection) { m_connection = connection; }
-    void nameLost(GDBusConnection*);
-    GVariant* getMetadataAsGVariant() const { return m_nowPlayingInfo.get(); }
-    GVariant* getPlaybackStatusAsGVariant(std::optional<const PlatformMediaSession*>);
-    GVariant* getActiveSessionPosition();
     void dispatch(PlatformMediaSession::RemoteControlCommandType, PlatformMediaSession::RemoteCommandArgument);
 
+    const GRefPtr<GDBusNodeInfo>& mprisInterface() const { return m_mprisInterface; }
+    PlatformMediaSession* nowPlayingEligibleSession();
+
 protected:
     void scheduleSessionStatusUpdate() final;
     void updateNowPlayingInfo();
@@ -73,8 +70,6 @@
 
     virtual void providePresentingApplicationPIDIfNecessary() { }
 
-    PlatformMediaSession* nowPlayingEligibleSession();
-
     void addSupportedCommand(PlatformMediaSession::RemoteControlCommandType) final;
     void removeSupportedCommand(PlatformMediaSession::RemoteControlCommandType) final;
     RemoteCommandListener::RemoteCommandsSet supportedCommands() const final;
@@ -82,8 +77,6 @@
     void resetHaveEverRegisteredAsNowPlayingApplicationForTesting() final { m_haveEverRegisteredAsNowPlayingApplication = false; };
 
 private:
-    void emitPropertiesChanged(GVariant*);
-
 #if !RELEASE_LOG_DISABLED
     const char* logClassName() const override { return "MediaSessionManagerGLib"; }
 #endif
@@ -91,14 +84,8 @@
     // NowPlayingManager::Client
     void didReceiveRemoteControlCommand(PlatformMediaSession::RemoteControlCommandType type, const PlatformMediaSession::RemoteCommandArgument& argument) final { processDidReceiveRemoteControlCommand(type, argument); }
 
-    String m_instanceId;
-    unsigned m_ownerId { 0 };
-    unsigned m_rootRegistrationId { 0 };
-    unsigned m_playerRegistrationId { 0 };
     bool m_isSeeking { false };
-    GRefPtr<GDBusConnection> m_connection;
     GRefPtr<GDBusNodeInfo> m_mprisInterface;
-    GRefPtr<GVariant> m_nowPlayingInfo;
 
     bool m_nowPlayingActive { false };
     bool m_registeredAsNowPlayingApplication { false };
@@ -111,8 +98,9 @@
     MediaUniqueIdentifier m_lastUpdatedNowPlayingInfoUniqueIdentifier;
 
     const std::unique_ptr<NowPlayingManager> m_nowPlayingManager;
+    HashMap<MediaSessionIdentifier, std::unique_ptr<MediaSessionGLib>> m_sessions;
 };
 
 } // namespace WebCore
 
-#endif // USE(GLIB)
+#endif // USE(GLIB) && ENABLE(MEDIA_SESSION)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to