⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 283437 in webkit


Ignore:
Timestamp:
Oct 2, 2021, 2:07:12 AM (5 years ago)
Author:
commit-queue@webkit.org
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 <pnormand@igalia.com> 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.
Location:
trunk/Source
Files:
2 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r283433 r283437  
     12021-10-02  Philippe Normand  <pnormand@igalia.com>
     2
     3        [GLib] Media session manager unable to handle more than one session
     4        https://bugs.webkit.org/show_bug.cgi?id=230250
     5
     6        Reviewed by Adrian Perez de Castro.
     7
     8        * wtf/glib/GRefPtr.h: Forward-declare GDBusConnection.
     9
    1102021-10-01  Yusuke Suzuki  <ysuzuki@apple.com>
    211
  • trunk/Source/WTF/wtf/glib/GRefPtr.h

    r282307 r283437  
    3030
    3131extern "C" {
     32    typedef struct _GDBusConnection GDBusConnection;
    3233    typedef struct _GDBusNodeInfo GDBusNodeInfo;
    3334    GDBusNodeInfo* g_dbus_node_info_ref(GDBusNodeInfo*);
  • trunk/Source/WebCore/ChangeLog

    r283434 r283437  
     12021-10-02  Philippe Normand  <pnormand@igalia.com>
     2
     3        [GLib] Media session manager unable to handle more than one session
     4        https://bugs.webkit.org/show_bug.cgi?id=230250
     5
     6        Reviewed by Adrian Perez de Castro.
     7
     8        Each session now maintains its own connection to the D-Bus session, allowing to safely
     9        expose the corresponding MPRIS objecs on the bus. Most of the D-Bus and GVariant handling
     10        has been refactored to the new MediaSessionGLib module.
     11
     12        * platform/SourcesGLib.txt:
     13        * platform/audio/glib/MediaSessionGLib.cpp: Added.
     14        (WebCore::getCommand):
     15        (WebCore::handleMethodCall):
     16        (WebCore::getMprisProperty):
     17        (WebCore::handleGetProperty):
     18        (WebCore::handleSetProperty):
     19        (WebCore::MediaSessionGLib::create):
     20        (WebCore::MediaSessionGLib::MediaSessionGLib):
     21        (WebCore::MediaSessionGLib::~MediaSessionGLib):
     22        (WebCore::MediaSessionGLib::nameLost):
     23        (WebCore::MediaSessionGLib::emitPositionChanged):
     24        (WebCore::MediaSessionGLib::updateNowPlaying):
     25        (WebCore::MediaSessionGLib::getMetadataAsGVariant):
     26        (WebCore::MediaSessionGLib::getPlaybackStatusAsGVariant):
     27        (WebCore::MediaSessionGLib::emitPropertiesChanged):
     28        (WebCore::MediaSessionGLib::playbackStatusChanged):
     29        (WebCore::MediaSessionGLib::getActiveSessionPosition):
     30        * platform/audio/glib/MediaSessionGLib.h: Added.
     31        (WebCore::MediaSessionGLib::manager const):
     32        * platform/audio/glib/MediaSessionManagerGLib.cpp:
     33        (WebCore::PlatformMediaSessionManager::create):
     34        (WebCore::MediaSessionManagerGLib::MediaSessionManagerGLib):
     35        (WebCore::MediaSessionManagerGLib::addSession):
     36        (WebCore::MediaSessionManagerGLib::removeSession):
     37        (WebCore::MediaSessionManagerGLib::sessionStateChanged):
     38        (WebCore::MediaSessionManagerGLib::clientCharacteristicsChanged):
     39        (WebCore::MediaSessionManagerGLib::updateNowPlayingInfo):
     40        * platform/audio/glib/MediaSessionManagerGLib.h:
     41        (WebCore::MediaSessionManagerGLib::mprisInterface const):
     42
    1432021-10-01  Nikos Mouchtaris  <nmouchtaris@apple.com>
    244
  • trunk/Source/WebCore/platform/SourcesGLib.txt

    r282307 r283437  
    2323
    2424platform/audio/glib/AudioBusGLib.cpp
     25platform/audio/glib/MediaSessionGLib.cpp
    2526platform/audio/glib/MediaSessionManagerGLib.cpp
    2627
  • trunk/Source/WebCore/platform/audio/glib/MediaSessionManagerGLib.cpp

    r282727 r283437  
    2222#if USE(GLIB) && ENABLE(MEDIA_SESSION)
    2323
    24 #include "ApplicationGLib.h"
    2524#include "AudioSession.h"
    2625#include "HTMLMediaElement.h"
     
    3231
    3332#include <gio/gio.h>
    34 #include <wtf/SortedArrayMap.h>
    3533
    3634// https://specifications.freedesktop.org/mpris-spec/latest/
     
    111109    "</node>";
    112110
    113 #define DBUS_MPRIS_OBJECT_PATH "/org/mpris/MediaPlayer2"
    114 #define DBUS_MPRIS_PLAYER_INTERFACE "org.mpris.MediaPlayer2.Player"
    115 #define DBUS_MPRIS_TRACK_PATH "/org/mpris/MediaPlayer2/webkit"
    116 
    117111namespace WebCore {
    118112
    119113std::unique_ptr<PlatformMediaSessionManager> PlatformMediaSessionManager::create()
    120114{
    121     return makeUnique<MediaSessionManagerGLib>();
    122 }
    123 
    124 MediaSessionManagerGLib::MediaSessionManagerGLib()
    125     : m_nowPlayingManager(platformStrategies()->mediaStrategy().createNowPlayingManager())
    126 {
    127 }
    128 
    129 MediaSessionManagerGLib::~MediaSessionManagerGLib()
    130 {
    131     if (m_ownerId)
    132         g_bus_unown_name(m_ownerId);
    133 }
    134 
    135 static std::optional<PlatformMediaSession::RemoteControlCommandType> getCommand(const char* name)
    136 {
    137     static const std::pair<ComparableASCIILiteral, PlatformMediaSession::RemoteControlCommandType> commandList[] = {
    138         { "Next", PlatformMediaSession::NextTrackCommand },
    139         { "Pause", PlatformMediaSession::PauseCommand },
    140         { "Play", PlatformMediaSession::PlayCommand },
    141         { "PlayPause", PlatformMediaSession::TogglePlayPauseCommand },
    142         { "Previous", PlatformMediaSession::PreviousTrackCommand },
    143         { "Seek", PlatformMediaSession::SeekToPlaybackPositionCommand },
    144         { "Stop", PlatformMediaSession::StopCommand }
    145     };
    146 
    147     static const SortedArrayMap map { commandList };
    148     auto value = map.get(name, PlatformMediaSession::RemoteControlCommandType::NoCommand);
    149     if (value == PlatformMediaSession::RemoteControlCommandType::NoCommand)
    150         return { };
    151     return value;
    152 }
    153 
    154 static void handleMethodCall(GDBusConnection* /* connection */, const char* /* sender */, const char* objectPath, const char* interfaceName, const char* methodName, GVariant* parameters, GDBusMethodInvocation* invocation, gpointer userData)
    155 {
    156     ASSERT(isMainThread());
    157     auto command = getCommand(methodName);
    158     if (!command) {
    159         g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "%s.%s.%s is not available now", objectPath, interfaceName, methodName);
    160         return;
    161     }
    162     auto& manager = *reinterpret_cast<MediaSessionManagerGLib*>(userData);
    163     PlatformMediaSession::RemoteCommandArgument argument;
    164     if (*command == PlatformMediaSession::SeekToPlaybackPositionCommand) {
    165         int64_t offset;
    166         g_variant_get(parameters, "(x)", &offset);
    167         argument.time = offset / 1000000;
    168     }
    169     manager.dispatch(*command, argument);
    170     g_dbus_method_invocation_return_value(invocation, nullptr);
    171 }
    172 
    173 enum class MprisProperty : uint8_t {
    174     NoProperty,
    175     CanControl,
    176     CanGoNext,
    177     CanGoPrevious,
    178     CanPause,
    179     CanPlay,
    180     CanQuit,
    181     CanRaise,
    182     CanSeek,
    183     DesktopEntry,
    184     GetMetadata,
    185     GetPlaybackStatus,
    186     GetPosition,
    187     HasTrackList,
    188     Identity,
    189     SupportedMimeTypes,
    190     SupportedUriSchemes,
    191 };
    192 
    193 static std::optional<MprisProperty> getMprisProperty(const char* propertyName)
    194 {
    195     static constexpr std::pair<ComparableASCIILiteral, MprisProperty> propertiesList[] {
    196         { "CanControl", MprisProperty::CanControl },
    197         { "CanGoNext", MprisProperty::CanGoNext },
    198         { "CanGoPrevious", MprisProperty::CanGoPrevious },
    199         { "CanPause", MprisProperty::CanPause },
    200         { "CanPlay", MprisProperty::CanPlay },
    201         { "CanQuit", MprisProperty::CanQuit },
    202         { "CanRaise", MprisProperty::CanRaise },
    203         { "CanSeek", MprisProperty::CanSeek },
    204         { "DesktopEntry", MprisProperty::DesktopEntry },
    205         { "HasTrackList", MprisProperty::HasTrackList },
    206         { "Identity", MprisProperty::Identity },
    207         { "Metadata", MprisProperty::GetMetadata },
    208         { "PlaybackStatus", MprisProperty::GetPlaybackStatus },
    209         { "Position", MprisProperty::GetPosition },
    210         { "SupportedMimeTypes", MprisProperty::SupportedMimeTypes },
    211         { "SupportedUriSchemes", MprisProperty::SupportedUriSchemes }
    212     };
    213     static constexpr SortedArrayMap map { propertiesList };
    214     auto value = map.get(propertyName, MprisProperty::NoProperty);
    215     if (value == MprisProperty::NoProperty)
    216         return { };
    217     return value;
    218 }
    219 
    220 static GVariant* handleGetProperty(GDBusConnection*, const char* /* sender */, const char* objectPath, const char* interfaceName, const char* propertyName, GError** error, gpointer userData)
    221 {
    222     ASSERT(isMainThread());
    223     auto property = getMprisProperty(propertyName);
    224     if (!property) {
    225         g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "%s.%s %s is not supported", objectPath, interfaceName, propertyName);
     115    GUniqueOutPtr<GError> error;
     116    auto mprisInterface = adoptGRef(g_dbus_node_info_new_for_xml(s_mprisInterface, &error.outPtr()));
     117    if (!mprisInterface) {
     118        g_warning("Failed at parsing XML Interface definition: %s", error->message);
    226119        return nullptr;
    227120    }
    228 
    229     auto& manager = *reinterpret_cast<MediaSessionManagerGLib*>(userData);
    230     switch (property.value()) {
    231     case MprisProperty::NoProperty:
    232         break;
    233     case MprisProperty::SupportedUriSchemes:
    234     case MprisProperty::SupportedMimeTypes:
    235         return g_variant_new_strv(nullptr, 0);
    236     case MprisProperty::GetPlaybackStatus:
    237         return manager.getPlaybackStatusAsGVariant({ });
    238     case MprisProperty::GetMetadata: {
    239         auto* variant = manager.getMetadataAsGVariant();
    240         if (!variant)
    241             return nullptr;
    242         return g_variant_ref(variant);
    243     }
    244     case MprisProperty::GetPosition:
    245         return manager.getActiveSessionPosition();
    246     case MprisProperty::Identity:
    247         return g_variant_new_string(getApplicationName());
    248     case MprisProperty::DesktopEntry:
    249         return g_variant_new_string("");
    250     case MprisProperty::HasTrackList:
    251     case MprisProperty::CanQuit:
    252     case MprisProperty::CanRaise:
    253         return g_variant_new_boolean(false);
    254     case MprisProperty::CanSeek:
    255     case MprisProperty::CanControl:
    256     case MprisProperty::CanGoNext:
    257     case MprisProperty::CanGoPrevious:
    258     case MprisProperty::CanPlay:
    259     case MprisProperty::CanPause:
    260         return g_variant_new_boolean(true);
    261     }
    262 
    263     return nullptr;
    264 }
    265 
    266 static gboolean handleSetProperty(GDBusConnection*, const char* /* sender */, const char* /* objectPath */, const char* interfaceName, const char* propertyName, GVariant*, GError** error, gpointer)
    267 {
    268     ASSERT(isMainThread());
    269     g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED, "%s:%s setting is not supported", interfaceName, propertyName);
    270     return FALSE;
    271 }
    272 
    273 static const GDBusInterfaceVTable gInterfaceVTable = {
    274     handleMethodCall, handleGetProperty, handleSetProperty, { nullptr }
    275 };
    276 
    277 bool MediaSessionManagerGLib::setupMpris()
    278 {
    279     if (m_ownerId)
    280         return true;
    281 
    282     const auto& applicationID = getApplicationID();
    283     m_instanceId = applicationID.isEmpty() ? makeString("org.mpris.MediaPlayer2.webkit.instance", getpid()) : makeString("org.mpris.MediaPlayer2.", applicationID.ascii().data());
    284 
    285     m_ownerId = g_bus_own_name(G_BUS_TYPE_SESSION, m_instanceId.ascii().data(),
    286         G_BUS_NAME_OWNER_FLAGS_NONE, reinterpret_cast<GBusAcquiredCallback>(+[](GDBusConnection* connection, const gchar*, gpointer userData) {
    287             auto& manager = *reinterpret_cast<MediaSessionManagerGLib*>(userData);
    288             manager.busAcquired(connection);
    289         }),
    290         reinterpret_cast<GBusNameAcquiredCallback>(+[](GDBusConnection* connection, const char*, gpointer userData) {
    291             auto& manager = *reinterpret_cast<MediaSessionManagerGLib*>(userData);
    292             manager.nameAcquired(connection);
    293         }),
    294         reinterpret_cast<GBusNameLostCallback>(+[](GDBusConnection* connection, const char*, gpointer userData) {
    295             auto& manager = *reinterpret_cast<MediaSessionManagerGLib*>(userData);
    296             manager.nameLost(connection);
    297         }), this, nullptr);
    298 
    299     GUniqueOutPtr<GError> error;
    300     m_mprisInterface = adoptGRef(g_dbus_node_info_new_for_xml(s_mprisInterface, &error.outPtr()));
    301     if (!m_mprisInterface) {
    302         g_warning("Failed at parsing XML Interface definition: %s", error->message);
    303         return false;
    304     }
    305 
    306     return true;
    307 }
    308 
    309 void MediaSessionManagerGLib::busAcquired(GDBusConnection* connection)
    310 {
    311     GUniqueOutPtr<GError> error;
    312     m_rootRegistrationId = g_dbus_connection_register_object(connection, DBUS_MPRIS_OBJECT_PATH, m_mprisInterface->interfaces[0],
    313         &gInterfaceVTable, this, nullptr, &error.outPtr());
    314 
    315     if (!m_rootRegistrationId) {
    316         g_warning("Failed to register MPRIS D-Bus object: %s", error->message);
    317         return;
    318     }
    319 
    320     m_playerRegistrationId = g_dbus_connection_register_object(connection, DBUS_MPRIS_OBJECT_PATH, m_mprisInterface->interfaces[1],
    321         &gInterfaceVTable, this, nullptr, &error.outPtr());
    322 
    323     if (!m_playerRegistrationId)
    324         g_warning("Failed at MPRIS object registration: %s", error->message);
    325 }
    326 
    327 void MediaSessionManagerGLib::nameLost(GDBusConnection* connection)
    328 {
    329     if (UNLIKELY(!m_connection)) {
    330         g_warning("Unable to acquire MPRIS D-Bus session ownership for name %s", m_instanceId.ascii().data());
    331         return;
    332     }
    333 
    334     m_connection = nullptr;
    335     if (!m_rootRegistrationId)
    336         return;
    337 
    338     if (g_dbus_connection_unregister_object(connection, m_rootRegistrationId))
    339         m_rootRegistrationId = 0;
    340     else
    341         g_warning("Unable to unregister MPRIS D-Bus object.");
    342 
    343     if (!m_playerRegistrationId)
    344         return;
    345 
    346     if (g_dbus_connection_unregister_object(connection, m_playerRegistrationId))
    347         m_playerRegistrationId = 0;
    348     else
    349         g_warning("Unable to unregister MPRIS D-Bus player object.");
    350 }
     121    return makeUnique<MediaSessionManagerGLib>(WTFMove(mprisInterface));
     122}
     123
     124MediaSessionManagerGLib::MediaSessionManagerGLib(GRefPtr<GDBusNodeInfo>&& mprisInterface)
     125    : m_mprisInterface(WTFMove(mprisInterface))
     126    , m_nowPlayingManager(platformStrategies()->mediaStrategy().createNowPlayingManager())
     127{
     128}
     129
     130MediaSessionManagerGLib::~MediaSessionManagerGLib() = default;
    351131
    352132void MediaSessionManagerGLib::beginInterruption(PlatformMediaSession::InterruptionType type)
     
    387167}
    388168
    389 void MediaSessionManagerGLib::addSession(PlatformMediaSession& session)
    390 {
    391     if (!setupMpris())
     169void MediaSessionManagerGLib::addSession(PlatformMediaSession& platformSession)
     170{
     171    auto identifier = platformSession.mediaSessionIdentifier();
     172    auto session = MediaSessionGLib::create(*this, identifier);
     173    if (!session)
    392174        return;
    393175
     176    m_sessions.add(identifier, WTFMove(session));
    394177    m_nowPlayingManager->addClient(*this);
    395178
    396     PlatformMediaSessionManager::addSession(session);
     179    PlatformMediaSessionManager::addSession(platformSession);
    397180}
    398181
     
    401184    PlatformMediaSessionManager::removeSession(session);
    402185
    403     if (hasNoSession()) {
     186    m_sessions.remove(session.mediaSessionIdentifier());
     187    if (hasNoSession())
    404188        m_nowPlayingManager->removeClient(*this);
    405         if (m_ownerId)
    406             g_bus_unown_name(m_ownerId);
    407         m_ownerId = 0;
    408     }
     189
    409190    scheduleSessionStatusUpdate();
    410191}
     
    435216}
    436217
    437 void MediaSessionManagerGLib::sessionStateChanged(PlatformMediaSession& session)
    438 {
    439     PlatformMediaSessionManager::sessionStateChanged(session);
    440 
    441     GVariantBuilder builder;
    442     g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
    443     g_variant_builder_add(&builder, "{sv}", "PlaybackStatus", getPlaybackStatusAsGVariant(&session));
    444     emitPropertiesChanged(g_variant_new("(sa{sv}as)", DBUS_MPRIS_PLAYER_INTERFACE, &builder, nullptr));
    445     g_variant_builder_clear(&builder);
    446 }
    447 
    448 void MediaSessionManagerGLib::clientCharacteristicsChanged(PlatformMediaSession& session)
    449 {
    450     ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier());
     218void MediaSessionManagerGLib::sessionStateChanged(PlatformMediaSession& platformSession)
     219{
     220    PlatformMediaSessionManager::sessionStateChanged(platformSession);
     221
     222    auto session = m_sessions.get(platformSession.mediaSessionIdentifier());
     223    if (!session)
     224        return;
     225
     226    session->playbackStatusChanged(platformSession);
     227}
     228
     229void MediaSessionManagerGLib::clientCharacteristicsChanged(PlatformMediaSession& platformSession)
     230{
     231    ALWAYS_LOG(LOGIDENTIFIER, platformSession.logIdentifier());
    451232    if (m_isSeeking) {
    452233        m_isSeeking = false;
    453         GUniqueOutPtr<GError> error;
    454         int64_t position = session.nowPlayingInfo()->currentTime * 1000000;
    455         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()))
    456             g_warning("Failed to emit MPRIS Seeked signal: %s", error->message);
     234        auto session = m_sessions.get(platformSession.mediaSessionIdentifier());
     235        session->emitPositionChanged(platformSession.nowPlayingInfo()->currentTime);
    457236    }
    458237    scheduleSessionStatusUpdate();
     
    492271void MediaSessionManagerGLib::updateNowPlayingInfo()
    493272{
    494     std::optional<NowPlayingInfo> nowPlayingInfo;
    495     if (auto* session = nowPlayingEligibleSession())
    496         nowPlayingInfo = session->nowPlayingInfo();
    497 
    498     if (!nowPlayingInfo) {
     273    auto* platformSession = nowPlayingEligibleSession();
     274    if (!platformSession) {
    499275        if (m_registeredAsNowPlayingApplication) {
    500276            ALWAYS_LOG(LOGIDENTIFIER, "clearing now playing info");
     
    508284        m_lastUpdatedNowPlayingElapsedTime = NAN;
    509285        m_lastUpdatedNowPlayingInfoUniqueIdentifier = { };
    510         m_nowPlayingInfo.clear();
    511286        return;
    512287    }
     288
     289    auto nowPlayingInfo = platformSession->nowPlayingInfo();
     290    if (!nowPlayingInfo)
     291        return;
    513292
    514293    m_haveEverRegisteredAsNowPlayingApplication = true;
     
    537316    m_nowPlayingActive = nowPlayingInfo->allowsNowPlayingControlsVisibility;
    538317
    539     GVariantBuilder builder;
    540     g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
    541     g_variant_builder_add(&builder, "{sv}", "mpris:trackid", g_variant_new("o", DBUS_MPRIS_TRACK_PATH));
    542     g_variant_builder_add(&builder, "{sv}", "mpris:length", g_variant_new_int64(nowPlayingInfo->duration * 1000000));
    543     g_variant_builder_add(&builder, "{sv}", "xesam:title", g_variant_new_string(nowPlayingInfo->title.utf8().data()));
    544     g_variant_builder_add(&builder, "{sv}", "xesam:album", g_variant_new_string(nowPlayingInfo->album.utf8().data()));
    545     if (nowPlayingInfo->artwork)
    546         g_variant_builder_add(&builder, "{sv}", "mpris:artUrl", g_variant_new_string(nowPlayingInfo->artwork->src.utf8().data()));
    547 
    548     GVariantBuilder artistBuilder;
    549     g_variant_builder_init(&artistBuilder, G_VARIANT_TYPE("as"));
    550     g_variant_builder_add(&artistBuilder, "s", nowPlayingInfo->artist.utf8().data());
    551     g_variant_builder_add(&builder, "{sv}", "xesam:artist", g_variant_builder_end(&artistBuilder));
    552 
    553     m_nowPlayingInfo = g_variant_builder_end(&builder);
    554 
    555     GVariantBuilder propertiesBuilder;
    556     g_variant_builder_init(&propertiesBuilder, G_VARIANT_TYPE("a{sv}"));
    557     g_variant_builder_add(&propertiesBuilder, "{sv}", "Metadata", m_nowPlayingInfo.get());
    558     emitPropertiesChanged(g_variant_new("(sa{sv}as)", DBUS_MPRIS_PLAYER_INTERFACE, &propertiesBuilder, nullptr));
    559     g_variant_builder_clear(&propertiesBuilder);
    560 }
    561 
    562 GVariant* MediaSessionManagerGLib::getPlaybackStatusAsGVariant(std::optional<const PlatformMediaSession*> session)
    563 {
    564     auto state = [this, session = WTFMove(session)]() -> PlatformMediaSession::State {
    565         if (session)
    566             return session.value()->state();
    567 
    568         auto* nowPlayingSession = nowPlayingEligibleSession();
    569         if (nowPlayingSession)
    570             return nowPlayingSession->state();
    571 
    572         return PlatformMediaSession::State::Idle;
    573     }();
    574 
    575     switch (state) {
    576     case PlatformMediaSession::State::Autoplaying:
    577     case PlatformMediaSession::State::Playing:
    578         return g_variant_new_string("Playing");
    579     case PlatformMediaSession::State::Paused:
    580         return g_variant_new_string("Paused");
    581     case PlatformMediaSession::State::Idle:
    582     case PlatformMediaSession::State::Interrupted:
    583         return g_variant_new_string("Stopped");
    584     }
    585     ASSERT_NOT_REACHED();
    586     return nullptr;
    587 }
    588 
    589 GVariant* MediaSessionManagerGLib::getActiveSessionPosition()
    590 {
    591     auto* session = nowPlayingEligibleSession();
    592     return g_variant_new_int64(session ? session->nowPlayingInfo()->currentTime * 1000000 : 0);
     318    auto session = m_sessions.get(platformSession->mediaSessionIdentifier());
     319    session->updateNowPlaying(*nowPlayingInfo);
    593320}
    594321
     
    599326}
    600327
    601 void MediaSessionManagerGLib::emitPropertiesChanged(GVariant* parameters)
    602 {
    603     if (!m_connection)
    604         return;
    605 
    606     GUniqueOutPtr<GError> error;
    607     if (!g_dbus_connection_emit_signal(m_connection.get(), nullptr, DBUS_MPRIS_OBJECT_PATH, "org.freedesktop.DBus.Properties", "PropertiesChanged", parameters, &error.outPtr()))
    608         g_warning("Failed to emit MPRIS properties changed: %s", error->message);
    609 }
    610 
    611328} // namespace WebCore
    612329
    613 #endif // USE(GLIB)
     330#endif // USE(GLIB) && ENABLE(MEDIA_SESSION)
  • trunk/Source/WebCore/platform/audio/glib/MediaSessionManagerGLib.h

    r282727 r283437  
    2121#if USE(GLIB) && ENABLE(MEDIA_SESSION)
    2222
     23#include "MediaSessionIdentifier.h"
    2324#include "NowPlayingManager.h"
    2425#include "PlatformMediaSessionManager.h"
     
    2829
    2930struct NowPlayingInfo;
     31class MediaSessionGLib;
    3032
    3133class MediaSessionManagerGLib
     
    3436    WTF_MAKE_FAST_ALLOCATED;
    3537public:
    36     MediaSessionManagerGLib();
     38    MediaSessionManagerGLib(GRefPtr<GDBusNodeInfo>&&);
    3739    ~MediaSessionManagerGLib();
    38 
    39     bool setupMpris();
    4040
    4141    void beginInterruption(PlatformMediaSession::InterruptionType) final;
     
    4949    bool haveEverRegisteredAsNowPlayingApplication() const final { return m_haveEverRegisteredAsNowPlayingApplication; }
    5050
    51     void busAcquired(GDBusConnection*);
    52     void nameAcquired(GDBusConnection* connection) { m_connection = connection; }
    53     void nameLost(GDBusConnection*);
    54     GVariant* getMetadataAsGVariant() const { return m_nowPlayingInfo.get(); }
    55     GVariant* getPlaybackStatusAsGVariant(std::optional<const PlatformMediaSession*>);
    56     GVariant* getActiveSessionPosition();
    5751    void dispatch(PlatformMediaSession::RemoteControlCommandType, PlatformMediaSession::RemoteCommandArgument);
     52
     53    const GRefPtr<GDBusNodeInfo>& mprisInterface() const { return m_mprisInterface; }
     54    PlatformMediaSession* nowPlayingEligibleSession();
    5855
    5956protected:
     
    7471    virtual void providePresentingApplicationPIDIfNecessary() { }
    7572
    76     PlatformMediaSession* nowPlayingEligibleSession();
    77 
    7873    void addSupportedCommand(PlatformMediaSession::RemoteControlCommandType) final;
    7974    void removeSupportedCommand(PlatformMediaSession::RemoteControlCommandType) final;
     
    8378
    8479private:
    85     void emitPropertiesChanged(GVariant*);
    86 
    8780#if !RELEASE_LOG_DISABLED
    8881    const char* logClassName() const override { return "MediaSessionManagerGLib"; }
     
    9285    void didReceiveRemoteControlCommand(PlatformMediaSession::RemoteControlCommandType type, const PlatformMediaSession::RemoteCommandArgument& argument) final { processDidReceiveRemoteControlCommand(type, argument); }
    9386
    94     String m_instanceId;
    95     unsigned m_ownerId { 0 };
    96     unsigned m_rootRegistrationId { 0 };
    97     unsigned m_playerRegistrationId { 0 };
    9887    bool m_isSeeking { false };
    99     GRefPtr<GDBusConnection> m_connection;
    10088    GRefPtr<GDBusNodeInfo> m_mprisInterface;
    101     GRefPtr<GVariant> m_nowPlayingInfo;
    10289
    10390    bool m_nowPlayingActive { false };
     
    11299
    113100    const std::unique_ptr<NowPlayingManager> m_nowPlayingManager;
     101    HashMap<MediaSessionIdentifier, std::unique_ptr<MediaSessionGLib>> m_sessions;
    114102};
    115103
    116104} // namespace WebCore
    117105
    118 #endif // USE(GLIB)
     106#endif // USE(GLIB) && ENABLE(MEDIA_SESSION)
Note: See TracChangeset for help on using the changeset viewer.