diff --git a/src/common/dbus.h b/src/common/dbus.h index 282f008d9..3d2dc702e 100644 --- a/src/common/dbus.h +++ b/src/common/dbus.h @@ -38,4 +38,9 @@ DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result); bool ffDBusGetPropertyUint(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, uint32_t* result); +static inline DBusMessage* ffDBusGetAllProperties(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface) +{ + return ffDBusGetMethodReply(dbus, busName, objectPath, "org.freedesktop.DBus.Properties", "GetAll", interface); +} + #endif // FF_HAVE_DBUS diff --git a/src/detection/media/media_linux.c b/src/detection/media/media_linux.c index 43e3f2115..a4953de50 100644 --- a/src/detection/media/media_linux.c +++ b/src/detection/media/media_linux.c @@ -17,35 +17,22 @@ continue; \ } -static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResult* result) +static bool parseMprisMetadata(FFDBusData* data, DBusMessageIter* rootIterator, FFMediaResult* result) { - DBusMessage* reply = ffDBusGetProperty(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", "Metadata"); - if(reply == NULL) - return false; - - DBusMessageIter rootIterator; - if(!data->lib->ffdbus_message_iter_init(reply, &rootIterator)) - { - data->lib->ffdbus_message_unref(reply); - return false; - } - - if(data->lib->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_VARIANT) - { - data->lib->ffdbus_message_unref(reply); - return false; - } - - DBusMessageIter variantIterator; - data->lib->ffdbus_message_iter_recurse(&rootIterator, &variantIterator); - if(data->lib->ffdbus_message_iter_get_arg_type(&variantIterator) != DBUS_TYPE_ARRAY) - { - data->lib->ffdbus_message_unref(reply); - return false; - } - DBusMessageIter arrayIterator; - data->lib->ffdbus_message_iter_recurse(&variantIterator, &arrayIterator); + + if (data->lib->ffdbus_message_iter_get_arg_type(rootIterator) == DBUS_TYPE_VARIANT) + { + DBusMessageIter variantIterator; + data->lib->ffdbus_message_iter_recurse(rootIterator, &variantIterator); + if(data->lib->ffdbus_message_iter_get_arg_type(&variantIterator) != DBUS_TYPE_ARRAY) + return false; + data->lib->ffdbus_message_iter_recurse(&variantIterator, &arrayIterator); + } + else + { + data->lib->ffdbus_message_iter_recurse(rootIterator, &arrayIterator); + } while(true) { @@ -66,13 +53,17 @@ static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResul data->lib->ffdbus_message_iter_next(&dictIterator); - if(ffStrEquals(key, "xesam:title")) + if(!ffStrStartsWith(key, "xesam:")) + FF_DBUS_ITER_CONTINUE(data, &arrayIterator) + + key += strlen("xesam:"); + if(ffStrEquals(key, "title")) ffDBusGetString(data, &dictIterator, &result->song); - else if(ffStrEquals(key, "xesam:album")) + else if(ffStrEquals(key, "album")) ffDBusGetString(data, &dictIterator, &result->album); - else if(ffStrEquals(key, "xesam:artist")) + else if(ffStrEquals(key, "artist")) ffDBusGetString(data, &dictIterator, &result->artist); - else if(ffStrEquals(key, "xesam:url")) + else if(ffStrEquals(key, "url")) ffDBusGetString(data, &dictIterator, &result->url); if(result->song.length > 0 && result->artist.length > 0 && result->album.length > 0 && result->url.length > 0) @@ -81,7 +72,53 @@ static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResul FF_DBUS_ITER_CONTINUE(data, &arrayIterator) } - data->lib->ffdbus_message_unref(reply); + return true; +} + +static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResult* result) +{ + // Get all properties at once to reduce the number of IPCs + DBusMessage* reply = ffDBusGetAllProperties(data, busName, "/org/mpris/MediaPlayer2", ""); + if(reply == NULL) + return false; + + DBusMessageIter rootIterator; + if(!data->lib->ffdbus_message_iter_init(reply, &rootIterator) && + data->lib->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_ARRAY) + { + data->lib->ffdbus_message_unref(reply); + return false; + } + + DBusMessageIter arrayIterator; + data->lib->ffdbus_message_iter_recurse(&rootIterator, &arrayIterator); + + FF_STRBUF_AUTO_DESTROY desktopIdentity = ffStrbufCreate(); + + while(true) + { + if(data->lib->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_DICT_ENTRY) + FF_DBUS_ITER_CONTINUE(data, &arrayIterator) + + DBusMessageIter dictIterator; + data->lib->ffdbus_message_iter_recurse(&arrayIterator, &dictIterator); + + const char* key; + data->lib->ffdbus_message_iter_get_basic(&dictIterator, &key); + + data->lib->ffdbus_message_iter_next(&dictIterator); + + if(ffStrEquals(key, "Metadata")) + parseMprisMetadata(data, &dictIterator, result); + else if(ffStrEquals(key, "PlaybackStatus")) + ffDBusGetString(data, &dictIterator, &result->status); + else if(ffStrEquals(key, "Identity")) + ffDBusGetString(data, &dictIterator, &result->player); + else if(ffStrEquals(key, "DesktopEntry")) + ffDBusGetString(data, &dictIterator, &desktopIdentity); + + FF_DBUS_ITER_CONTINUE(data, &arrayIterator) + } if(result->song.length == 0) { @@ -91,17 +128,20 @@ static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResul return false; } - ffDBusGetPropertyString(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", "PlaybackStatus", &result->status); + if (result->player.length == 0) + { + if (desktopIdentity.length > 0) + { + ffStrbufDestroy(&result->player); + ffStrbufInitMove(&result->player, &desktopIdentity); + } + else + { + ffStrbufAppend(&result->player, &result->playerId); + } + } - //Set short bus name - ffStrbufAppendS(&result->playerId, busName + sizeof(FF_DBUS_MPRIS_PREFIX) - 1); - - //We found a song, get the player name - ffDBusGetPropertyString(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "Identity", &result->player); - if(result->player.length == 0) - ffDBusGetPropertyString(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "DesktopEntry", &result->player); - if(result->player.length == 0) - ffStrbufAppend(&result->player, &result->playerId); + data->lib->ffdbus_message_unref(reply); return true; } @@ -122,9 +162,9 @@ static void getCustomBus(FFDBusData* data, const FFstrbuf* playerName, FFMediaRe static void getBestBus(FFDBusData* data, FFMediaResult* result) { if( - getBusProperties(data, FF_DBUS_MPRIS_PREFIX"spotify", result) || - getBusProperties(data, FF_DBUS_MPRIS_PREFIX"vlc", result) || - getBusProperties(data, FF_DBUS_MPRIS_PREFIX"plasma-browser-integration", result) + getBusProperties(data, FF_DBUS_MPRIS_PREFIX "spotify", result) || + getBusProperties(data, FF_DBUS_MPRIS_PREFIX "vlc", result) || + getBusProperties(data, FF_DBUS_MPRIS_PREFIX "plasma-browser-integration", result) ) return; DBusMessage* reply = ffDBusGetMethodReply(data, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames", NULL);