Skip to content

Commit

Permalink
Greatly improved detection of media player name
Browse files Browse the repository at this point in the history
  • Loading branch information
LinusDierheimer committed Mar 22, 2022
1 parent ad006b4 commit 0916258
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 54 deletions.
6 changes: 3 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
cmake_minimum_required(VERSION 3.1.0) # Threads::Threads

project(fastfetch
VERSION 1.0.0
VERSION 1.1.0
LANGUAGES C
)

#e.g. -alpha or -beta or +1
#e.g. +1
#This allows to track builds between versions, without GitHub creating a new release
set(PROJECT_VERSION_EXTRA "+1")
set(PROJECT_VERSION_EXTRA "")

include(GNUInstallDirs)

Expand Down
174 changes: 133 additions & 41 deletions src/detection/media.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "fastfetch.h"

#include <ctype.h>
#include <string.h>
#include <pthread.h>

Expand Down Expand Up @@ -53,20 +54,25 @@ static bool getValue(DBusMessageIter* iter, FFstrbuf* result, DBusData* data)
return true;
}

if(argType != DBUS_TYPE_ARRAY)
if(argType != DBUS_TYPE_VARIANT && argType != DBUS_TYPE_ARRAY)
return false;

DBusMessageIter arrayIter;
data->ffdbus_message_iter_recurse(iter, &arrayIter);
DBusMessageIter subIter;
data->ffdbus_message_iter_recurse(iter, &subIter);

if(argType == DBUS_TYPE_VARIANT)
return getValue(&subIter, result, data);

//At this point we have an array

bool foundAValue = false;

while(true)
{
if((foundAValue = getValue(&arrayIter, result, data)))
if((foundAValue = getValue(&subIter, result, data)))
ffStrbufAppendS(result, ", ");

FF_DBUS_ITER_CONTINUE(arrayIter);
FF_DBUS_ITER_CONTINUE(subIter);
}

if(foundAValue)
Expand All @@ -75,51 +81,87 @@ static bool getValue(DBusMessageIter* iter, FFstrbuf* result, DBusData* data)
return foundAValue;
}

static bool detectSong(const char* player, FFMediaResult* result, DBusData* data)
static DBusMessage* getProperty(const char* busName, const char* objectPath, const char* interface, const char* property, DBusData* data)
{
DBusMessage* message = data->ffdbus_message_new_method_call(player, "/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties", "Get");
DBusMessage* message = data->ffdbus_message_new_method_call(busName, objectPath, "org.freedesktop.DBus.Properties", "Get");
if(message == NULL)
return false;
return NULL;

DBusMessageIter requestIterator;
data->ffdbus_message_iter_init_append(message, &requestIterator);

const char* arg1 = "org.mpris.MediaPlayer2.Player";
if(!data->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &arg1))
if(!data->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &interface))
{
data->ffdbus_message_unref(message);
return false;
return NULL;
}

const char* arg2 = "Metadata";
if(!data->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &arg2))
if(!data->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &property))
{
data->ffdbus_message_unref(message);
return false;
return NULL;
}

DBusPendingCall* pending;
bool sendSuccessfull = data->ffdbus_connection_send_with_reply(data->connection, message, &pending, DBUS_TIMEOUT_USE_DEFAULT);
data->ffdbus_message_unref(message);
if(pending == NULL || !sendSuccessfull)
return false;
return NULL;

data->ffdbus_connection_flush(data->connection);
data->ffdbus_pending_call_block(pending);

DBusMessage* reply = data->ffdbus_pending_call_steal_reply(pending);

data->ffdbus_pending_call_unref(pending);

return reply;
}

static void getPropertyString(const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result, DBusData* data)
{
DBusMessage* reply = getProperty(busName, objectPath, interface, property, data);
if(reply == NULL)
return;

DBusMessageIter rootIterator;
if(!data->ffdbus_message_iter_init(reply, &rootIterator))
{
data->ffdbus_message_unref(reply);
return;
}

getValue(&rootIterator, result, data);

data->ffdbus_message_unref(reply);
}

static bool getBusProperties(const char* busName, FFMediaResult* result, DBusData* data)
{
DBusMessage* reply = getProperty(busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", "Metadata", data);
if(reply == NULL)
return false;

DBusMessageIter rootIterator;
if(!data->ffdbus_message_iter_init(reply, &rootIterator) || data->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_VARIANT)
if(!data->ffdbus_message_iter_init(reply, &rootIterator))
{
data->ffdbus_message_unref(reply);
return false;
}

if(data->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_VARIANT)
{
data->ffdbus_message_unref(reply);
return false;
}

DBusMessageIter variantIterator;
data->ffdbus_message_iter_recurse(&rootIterator, &variantIterator);
if(data->ffdbus_message_iter_get_arg_type(&variantIterator) != DBUS_TYPE_ARRAY)
{
data->ffdbus_message_unref(reply);
return false;
}

DBusMessageIter arrayIterator;
data->ffdbus_message_iter_recurse(&variantIterator, &arrayIterator);
Expand All @@ -143,55 +185,60 @@ static bool detectSong(const char* player, FFMediaResult* result, DBusData* data

data->ffdbus_message_iter_next(&dictIterator);

if(data->ffdbus_message_iter_get_arg_type(&dictIterator) != DBUS_TYPE_VARIANT)
FF_DBUS_ITER_CONTINUE(arrayIterator)

DBusMessageIter valueIter;
data->ffdbus_message_iter_recurse(&dictIterator, &valueIter);

if(strcmp(key, "xesam:title") == 0)
getValue(&valueIter, &result->song, data);
getValue(&dictIterator, &result->song, data);
else if(strcmp(key, "xesam:album") == 0)
getValue(&valueIter, &result->album, data);
getValue(&dictIterator, &result->album, data);
else if(strcmp(key, "xesam:artist") == 0)
getValue(&valueIter, &result->artist, data);
getValue(&dictIterator, &result->artist, data);
else if(strcmp(key, "xesam:url") == 0)
getValue(&dictIterator, &result->url, data);

if(result->song.length > 0 && result->artist.length > 0 && result->album.length > 0)
break;

FF_DBUS_ITER_CONTINUE(arrayIterator)
}

data->ffdbus_message_unref(reply);

if(result->song.length == 0)
{
ffStrbufClear(&result->artist);
ffStrbufClear(&result->album);
return false;
}

//We found a song, get the player name

getPropertyString(busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "Identity", &result->player, data);

if(result->player.length == 0)
getPropertyString(busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "DesktopEntry", &result->player, data);

return true;
}

static void getCustomPlayer(FFinstance* instance, FFMediaResult* result, DBusData* data)
static void getCustomBus(FFinstance* instance, FFMediaResult* result, DBusData* data)
{
if(ffStrbufStartsWithS(&instance->config.playerName, FF_DBUS_MPRIS_PREFIX))
{
detectSong(instance->config.playerName.chars, result, data);
ffStrbufAppendS(&result->player, instance->config.playerName.chars + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
ffStrbufAppendS(&result->busNameShort, instance->config.playerName.chars + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
getBusProperties(instance->config.playerName.chars, result, data);
return;
}

ffStrbufAppend(&result->busNameShort, &instance->config.playerName);

FFstrbuf busName;
ffStrbufInit(&busName);
ffStrbufAppendS(&busName, FF_DBUS_MPRIS_PREFIX);
ffStrbufAppend(&busName, &instance->config.playerName);
detectSong(busName.chars, result, data);
getBusProperties(busName.chars, result, data);
ffStrbufDestroy(&busName);

ffStrbufAppend(&result->player, &instance->config.playerName);
}

static void getBestPlayer(FFMediaResult* result, DBusData* data)
static void getBestBus(FFMediaResult* result, DBusData* data)
{
DBusMessage* message = data->ffdbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames");
if(message == NULL)
Expand Down Expand Up @@ -223,20 +270,22 @@ static void getBestPlayer(FFMediaResult* result, DBusData* data)
if(data->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_STRING)
FF_DBUS_ITER_CONTINUE(arrayIterator)

const char* name;
data->ffdbus_message_iter_get_basic(&arrayIterator, &name);
const char* busName;
data->ffdbus_message_iter_get_basic(&arrayIterator, &busName);

if(strncmp(name, FF_DBUS_MPRIS_PREFIX, sizeof(FF_DBUS_MPRIS_PREFIX) - 1) != 0)
if(strncmp(busName, FF_DBUS_MPRIS_PREFIX, sizeof(FF_DBUS_MPRIS_PREFIX) - 1) != 0)
FF_DBUS_ITER_CONTINUE(arrayIterator)

if(detectSong(name, result, data))
if(getBusProperties(busName, result, data))
{
ffStrbufAppendS(&result->player, name + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
ffStrbufAppendS(&result->busNameShort, busName + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
break;
}

FF_DBUS_ITER_CONTINUE(arrayIterator)
}

data->ffdbus_message_unref(reply);
}

static void getMedia(FFinstance* instance, FFMediaResult* result)
Expand Down Expand Up @@ -269,9 +318,9 @@ static void getMedia(FFinstance* instance, FFMediaResult* result)
}

if(instance->config.playerName.length > 0)
getCustomPlayer(instance, result, &data);
getCustomBus(instance, result, &data);
else
getBestPlayer(result, &data);
getBestBus(result, &data);

dlclose(dbus);
}
Expand All @@ -292,23 +341,66 @@ const FFMediaResult* ffDetectMedia(FFinstance* instance)
}
init = true;

ffStrbufInit(&result.busNameShort);
ffStrbufInit(&result.player);
ffStrbufInit(&result.playerPretty);
ffStrbufInit(&result.song);
ffStrbufInit(&result.artist);
ffStrbufInit(&result.album);
ffStrbufInit(&result.url);

#ifdef FF_HAVE_DBUS
getMedia(instance, &result);
#endif

//Set busNameShort if a custom player was given, but loading dbus failed
if(instance->config.playerName.length > 0 && result.player.length == 0)
{
if(ffStrbufStartsWithS(&instance->config.playerName, FF_DBUS_MPRIS_PREFIX))
ffStrbufAppendS(&result.player, instance->config.playerName.chars + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
ffStrbufAppendS(&result.busNameShort, instance->config.playerName.chars + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
else
ffStrbufAppend(&result.player, &instance->config.playerName);
ffStrbufAppend(&result.busNameShort, &instance->config.playerName);
}

//Set player to busNameShort, if detection failed
if(result.player.length == 0)
ffStrbufAppend(&result.player, &result.busNameShort);

//If we are on a website, prepend the website name
if(ffStrbufStartsWithS(&result.url, "https://www.")) {
ffStrbufAppendS(&result.playerPretty, result.url.chars + 12);
}
else if(ffStrbufStartsWithS(&result.url, "http://www.")) {
ffStrbufAppendS(&result.playerPretty, result.url.chars + 11);
}
else if(ffStrbufStartsWithS(&result.url, "https://")) {
ffStrbufAppendS(&result.playerPretty, result.url.chars + 8);
}
else if(ffStrbufStartsWithS(&result.url, "http://")) {
ffStrbufAppendS(&result.playerPretty, result.url.chars + 7);
}

//If we found a website name, make it more pretty
if(result.playerPretty.length > 0)
{
ffStrbufSubstrBeforeFirstC(&result.playerPretty, '/'); //Remove the path
ffStrbufSubstrBeforeLastC(&result.playerPretty, '.'); //Remove the TLD
}

//We may have removed everything
bool hasCustomPrettyName = result.playerPretty.length > 0;

if(hasCustomPrettyName)
{
result.playerPretty.chars[0] = (char) toupper(result.playerPretty.chars[0]);
ffStrbufAppendS(&result.playerPretty, " (");
}

ffStrbufAppend(&result.playerPretty, &result.player);

if(hasCustomPrettyName)
ffStrbufAppendC(&result.playerPretty, ')');

pthread_mutex_unlock(&mutex);
return &result;
}
11 changes: 7 additions & 4 deletions src/fastfetch.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,16 +304,19 @@ static inline void printCommandHelp(const char* command)
}
else if(strcasecmp(command, "player-format") == 0)
{
constructAndPrintCommandHelpFormat("player", "{}", 1,
"Player name"
constructAndPrintCommandHelpFormat("player", "{}", 3,
"Pretty player name",
"Player name",
"DBus bus name"
);
}
else if(strcasecmp(command, "song-format") == 0)
{
constructAndPrintCommandHelpFormat("song", "{2} - {3} - {1}", 3,
constructAndPrintCommandHelpFormat("song", "{2} - {3} - {1}", 4,
"Song name",
"Artist name",
"Album name"
"Album name",
"Song url"
);
}
else if(strcasecmp(command, "datetime-format") == 0 || strcasecmp(command, "date-format") == 0 || strcasecmp(command, "time-format") == 0)
Expand Down
5 changes: 4 additions & 1 deletion src/fastfetch.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,10 +257,13 @@ typedef struct FFTempsResult

typedef struct FFMediaResult
{
FFstrbuf player;
FFstrbuf busNameShort; //e.g. plasma-browser-integration
FFstrbuf player; // e.g. Google Chrome
FFstrbuf playerPretty; // e.g. YouTube (Google Chrome)
FFstrbuf song;
FFstrbuf artist;
FFstrbuf album;
FFstrbuf url;
} FFMediaResult;

typedef struct FFDateTimeResult
Expand Down
Loading

0 comments on commit 0916258

Please sign in to comment.