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)