Files
fastfetch/src/detection/media/media_linux.c
T

183 lines
6.0 KiB
C
Raw Normal View History

2022-02-13 23:51:13 +01:00
#include "fastfetch.h"
2022-09-19 20:05:23 +08:00
#include "detection/media/media.h"
#include "common/thread.h"
#include "util/stringUtils.h"
2022-02-13 23:51:13 +01:00
#include <string.h>
#define FF_DBUS_MPRIS_PREFIX "org.mpris.MediaPlayer2."
2022-04-29 21:44:32 +02:00
#define FF_DBUS_TIMEOUT_MILLISECONDS 35
2022-02-13 23:51:13 +01:00
#ifdef FF_HAVE_DBUS
2023-01-24 10:39:33 +01:00
#include "common/dbus.h"
#include "common/library.h"
#include "common/parsing.h"
2022-02-13 23:51:13 +01:00
2023-01-24 10:39:33 +01:00
static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResult* result)
2022-02-13 23:51:13 +01:00
{
2023-01-24 10:39:33 +01:00
DBusMessage* reply = ffDBusGetProperty(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", "Metadata");
2022-02-13 23:51:13 +01:00
if(reply == NULL)
return false;
DBusMessageIter rootIterator;
2023-01-24 10:39:33 +01:00
if(!data->lib->ffdbus_message_iter_init(reply, &rootIterator))
{
2023-01-24 10:39:33 +01:00
data->lib->ffdbus_message_unref(reply);
return false;
}
2023-01-24 10:39:33 +01:00
if(data->lib->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_VARIANT)
{
2023-01-24 10:39:33 +01:00
data->lib->ffdbus_message_unref(reply);
2022-02-13 23:51:13 +01:00
return false;
}
2022-02-13 23:51:13 +01:00
DBusMessageIter variantIterator;
2023-01-24 10:39:33 +01:00
data->lib->ffdbus_message_iter_recurse(&rootIterator, &variantIterator);
if(data->lib->ffdbus_message_iter_get_arg_type(&variantIterator) != DBUS_TYPE_ARRAY)
{
2023-01-24 10:39:33 +01:00
data->lib->ffdbus_message_unref(reply);
2022-02-13 23:51:13 +01:00
return false;
}
2022-02-13 23:51:13 +01:00
DBusMessageIter arrayIterator;
2023-01-24 10:39:33 +01:00
data->lib->ffdbus_message_iter_recurse(&variantIterator, &arrayIterator);
2022-02-13 23:51:13 +01:00
while(true)
{
2023-01-24 10:39:33 +01:00
if(data->lib->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_DICT_ENTRY)
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
2022-02-13 23:51:13 +01:00
DBusMessageIter dictIterator;
2023-01-24 10:39:33 +01:00
data->lib->ffdbus_message_iter_recurse(&arrayIterator, &dictIterator);
2022-02-13 23:51:13 +01:00
2023-01-24 10:39:33 +01:00
if(data->lib->ffdbus_message_iter_get_arg_type(&dictIterator) != DBUS_TYPE_STRING)
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
2022-02-13 23:51:13 +01:00
2023-01-24 10:39:33 +01:00
if(!data->lib->ffdbus_message_iter_has_next(&dictIterator))
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
2022-02-13 23:51:13 +01:00
const char* key;
2023-01-24 10:39:33 +01:00
data->lib->ffdbus_message_iter_get_basic(&dictIterator, &key);
2023-01-24 10:39:33 +01:00
data->lib->ffdbus_message_iter_next(&dictIterator);
2022-02-13 23:51:13 +01:00
if(ffStrEquals(key, "xesam:title"))
2023-01-24 10:39:33 +01:00
ffDBusGetValue(data, &dictIterator, &result->song);
else if(ffStrEquals(key, "xesam:album"))
2023-01-24 10:39:33 +01:00
ffDBusGetValue(data, &dictIterator, &result->album);
else if(ffStrEquals(key, "xesam:artist"))
2023-01-24 10:39:33 +01:00
ffDBusGetValue(data, &dictIterator, &result->artist);
else if(ffStrEquals(key, "xesam:url"))
2023-01-24 10:39:33 +01:00
ffDBusGetValue(data, &dictIterator, &result->url);
2022-02-13 23:51:13 +01:00
2022-09-11 13:09:33 +02:00
if(result->song.length > 0 && result->artist.length > 0 && result->album.length > 0 && result->url.length > 0)
2022-02-13 23:51:13 +01:00
break;
2023-01-24 10:39:33 +01:00
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
2022-02-13 23:51:13 +01:00
}
2023-01-24 10:39:33 +01:00
data->lib->ffdbus_message_unref(reply);
2022-02-13 23:51:13 +01:00
if(result->song.length == 0)
{
ffStrbufClear(&result->artist);
ffStrbufClear(&result->album);
ffStrbufClear(&result->url);
2022-02-13 23:51:13 +01:00
return false;
}
2022-09-11 13:09:33 +02:00
//Set short bus name
ffStrbufAppendS(&result->playerId, busName + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
2022-09-11 13:09:33 +02:00
//We found a song, get the player name
2023-01-24 10:39:33 +01:00
ffDBusGetPropertyString(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "Identity", &result->player);
if(result->player.length == 0)
2023-01-24 10:39:33 +01:00
ffDBusGetPropertyString(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "DesktopEntry", &result->player);
2022-09-11 13:09:33 +02:00
if(result->player.length == 0)
ffStrbufAppend(&result->player, &result->playerId);
2022-02-13 23:51:13 +01:00
return true;
}
2023-06-12 14:37:18 +08:00
static void getCustomBus(FFDBusData* data, const FFstrbuf* playerName, FFMediaResult* result)
2022-02-13 23:51:13 +01:00
{
2023-06-12 14:37:18 +08:00
if(ffStrbufStartsWithS(playerName, FF_DBUS_MPRIS_PREFIX))
2022-02-13 23:51:13 +01:00
{
2023-06-12 14:37:18 +08:00
getBusProperties(data, playerName->chars, result);
2022-02-13 23:51:13 +01:00
return;
}
FF_STRBUF_AUTO_DESTROY busName = ffStrbufCreateS(FF_DBUS_MPRIS_PREFIX);
2023-06-12 14:37:18 +08:00
ffStrbufAppend(&busName, playerName);
2023-01-24 10:39:33 +01:00
getBusProperties(data, busName.chars, result);
2022-02-13 23:51:13 +01:00
}
2023-01-24 10:39:33 +01:00
static void getBestBus(FFDBusData* data, FFMediaResult* result)
2022-02-13 23:51:13 +01:00
{
2022-09-11 13:09:33 +02:00
if(
2023-01-24 10:39:33 +01:00
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)
2022-09-11 13:09:33 +02:00
) return;
2023-01-24 10:39:33 +01:00
DBusMessage* reply = ffDBusGetMethodReply(data, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames");
2022-02-13 23:51:13 +01:00
if(reply == NULL)
return;
DBusMessageIter rootIterator;
2023-01-24 10:39:33 +01:00
if(!data->lib->ffdbus_message_iter_init(reply, &rootIterator) || data->lib->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_ARRAY)
2022-02-13 23:51:13 +01:00
return;
DBusMessageIter arrayIterator;
2023-01-24 10:39:33 +01:00
data->lib->ffdbus_message_iter_recurse(&rootIterator, &arrayIterator);
2022-02-13 23:51:13 +01:00
while(true)
{
2023-01-24 10:39:33 +01:00
if(data->lib->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_STRING)
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
2022-02-13 23:51:13 +01:00
const char* busName;
2023-01-24 10:39:33 +01:00
data->lib->ffdbus_message_iter_get_basic(&arrayIterator, &busName);
2022-02-13 23:51:13 +01:00
2023-06-19 15:38:37 +08:00
if(!ffStrStartsWith(busName, FF_DBUS_MPRIS_PREFIX))
2023-01-24 10:39:33 +01:00
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
2022-02-13 23:51:13 +01:00
2023-01-24 10:39:33 +01:00
if(getBusProperties(data, busName, result))
2022-02-13 23:51:13 +01:00
break;
2023-01-24 10:39:33 +01:00
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
2022-02-13 23:51:13 +01:00
}
2023-01-24 10:39:33 +01:00
data->lib->ffdbus_message_unref(reply);
2022-02-13 23:51:13 +01:00
}
static const char* getMedia(FFMediaResult* result)
2022-02-13 23:51:13 +01:00
{
2023-01-24 10:39:33 +01:00
FFDBusData data;
const char* error = ffDBusLoadData(DBUS_BUS_SESSION, &data);
2023-01-24 10:39:33 +01:00
if(error != NULL)
return error;
2022-02-13 23:51:13 +01:00
2023-06-12 14:37:18 +08:00
// FIXME: This is shared for both player and media module.
// However it uses an option in one specific module
if(instance.config.general.playerName.length > 0)
getCustomBus(&data, &instance.config.general.playerName, result);
2022-02-13 23:51:13 +01:00
else
2023-01-24 10:39:33 +01:00
getBestBus(&data, result);
2022-02-13 23:51:13 +01:00
return NULL;
2022-02-13 23:51:13 +01:00
}
#endif
void ffDetectMediaImpl(FFMediaResult* media)
2022-02-13 23:51:13 +01:00
{
#ifdef FF_HAVE_DBUS
const char* error = getMedia(media);
ffStrbufAppendS(&media->error, error);
#else
ffStrbufAppendS(&media->error, "Fastfetch was compiled without DBus support");
2022-02-13 23:51:13 +01:00
#endif
}