mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:14:37 +02:00
Media player and song detection!
This commit is contained in:
@@ -11,6 +11,7 @@ OPTION(ENABLE_XRANDR "Enable xrandr" ON)
|
||||
OPTION(ENABLE_X11 "Enable x11" ON)
|
||||
OPTION(ENABLE_GIO "Enable gio-2.0" ON)
|
||||
OPTION(ENABLE_DCONF "Enable dconf" ON)
|
||||
OPTION(ENABLE_DBUS "Enable dbus-1" ON)
|
||||
OPTION(ENABLE_XFCONF "Enable libxfconf-0" ON)
|
||||
OPTION(ENABLE_RPM "Enable rpm" ON)
|
||||
|
||||
@@ -78,6 +79,7 @@ add_library(libfastfetch STATIC
|
||||
src/detection/plasma.c
|
||||
src/detection/gtk.c
|
||||
src/detection/terminalShell.c
|
||||
src/detection/media.c
|
||||
src/detection/displayserver/displayServer.c
|
||||
src/detection/displayserver/wayland.c
|
||||
src/detection/displayserver/xcb.c
|
||||
@@ -113,6 +115,8 @@ add_library(libfastfetch STATIC
|
||||
src/modules/locale.c
|
||||
src/modules/localip.c
|
||||
src/modules/publicip.c
|
||||
src/modules/player.c
|
||||
src/modules/song.c
|
||||
src/modules/colors.c
|
||||
)
|
||||
|
||||
@@ -197,6 +201,15 @@ if(ENABLE_DCONF)
|
||||
endif(DCONF_FOUND)
|
||||
endif(ENABLE_DCONF)
|
||||
|
||||
if(ENABLE_DBUS)
|
||||
pkg_check_modules (DBUS dbus-1)
|
||||
if(DBUS_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_DBUS=1)
|
||||
else(DBUS_FOUND)
|
||||
message(WARNING "Package dbus-1 not found. Building without support.")
|
||||
endif(DBUS_FOUND)
|
||||
endif(ENABLE_DBUS)
|
||||
|
||||
if(ENABLE_XFCONF)
|
||||
pkg_check_modules (XFCONF libxfconf-0)
|
||||
if(XFCONF_FOUND)
|
||||
@@ -228,6 +241,7 @@ target_include_directories(libfastfetch
|
||||
PRIVATE ${X11_INCLUDE_DIRS}
|
||||
PRIVATE ${GIO_INCLUDE_DIRS}
|
||||
PRIVATE ${DCONF_INCLUDE_DIRS}
|
||||
PRIVATE ${DBUS_INCLUDE_DIRS}
|
||||
PRIVATE ${XFCONF_INCLUDE_DIRS}
|
||||
PRIVATE ${RPM_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
@@ -28,12 +28,18 @@ The following libraries are used if present at runtime:
|
||||
* [`libwayland-client`](https://wayland.freedesktop.org/): Better resolution performance and output in wayland sessions. Supports different refresh rates per monitor.
|
||||
* [`libGIO`](https://developer.gnome.org/gio/unstable/): Needed for values that are only stored GSettings.
|
||||
* [`libDConf`](https://developer.gnome.org/dconf/unstable/): Needed for values that are only stored in DConf + Fallback for GSettings.
|
||||
* [`libDBus`](https://www.freedesktop.org/wiki/Software/dbus): Needed for detecting current media player and song.
|
||||
* [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font.
|
||||
* [`librpm`](http://rpm.org/): Needed for rpm package count.
|
||||
|
||||
## Support status
|
||||
All categories not listed here should work without needing a specific implementation.
|
||||
|
||||
### Modules
|
||||
```
|
||||
Title, Separator, OS, Host, Kernel, Uptime, Processes, Packages, Shell, Resolution, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Disk, Battery, LocalIP, PublicIP, Player, Song, Locale, Colors, Break, Custom
|
||||
```
|
||||
|
||||
##### Logos
|
||||
```
|
||||
Android, Arch, Arco, Artix, CachyOS, CentOS, Debian, Endeavour, Fedora, Garuda, Gentoo, Manjaro, Mint, Pop!_OS, Ubuntu, Void
|
||||
|
||||
@@ -194,6 +194,10 @@ __fastfetch_completion()
|
||||
"--local-ip-key"
|
||||
"--public-ip-format"
|
||||
"--public-ip-key"
|
||||
"--player-format"
|
||||
"--player-key"
|
||||
"--song-format"
|
||||
"--song-key"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_PATH=(
|
||||
@@ -207,6 +211,7 @@ __fastfetch_completion()
|
||||
"--lib-X11"
|
||||
"--lib-gio"
|
||||
"--lib-DConf"
|
||||
"--lib-DBus"
|
||||
"--lib-XFConf"
|
||||
"--lib-RPM"
|
||||
"--battery-dir"
|
||||
|
||||
@@ -174,6 +174,10 @@ static void defaultConfig(FFinstance* instance)
|
||||
ffStrbufInitA(&instance->config.localIpFormat, 0);
|
||||
ffStrbufInitA(&instance->config.publicIpKey, 0);
|
||||
ffStrbufInitA(&instance->config.publicIpFormat, 0);
|
||||
ffStrbufInitA(&instance->config.playerKey, 0);
|
||||
ffStrbufInitA(&instance->config.playerFormat, 0);
|
||||
ffStrbufInitA(&instance->config.songKey, 0);
|
||||
ffStrbufInitA(&instance->config.songFormat, 0);
|
||||
|
||||
ffStrbufInitA(&instance->config.libPCI, 0);
|
||||
ffStrbufInitA(&instance->config.libVulkan, 0);
|
||||
@@ -184,6 +188,7 @@ static void defaultConfig(FFinstance* instance)
|
||||
ffStrbufInitA(&instance->config.libX11, 0);
|
||||
ffStrbufInitA(&instance->config.libGIO, 0);
|
||||
ffStrbufInitA(&instance->config.libDConf, 0);
|
||||
ffStrbufInitA(&instance->config.libDBus, 0);
|
||||
ffStrbufInitA(&instance->config.libXFConf, 0);
|
||||
ffStrbufInitA(&instance->config.librpm, 0);
|
||||
|
||||
@@ -200,6 +205,8 @@ static void defaultConfig(FFinstance* instance)
|
||||
instance->config.publicIpTimeout = 0;
|
||||
|
||||
ffStrbufInitA(&instance->config.osFile, 0);
|
||||
|
||||
ffStrbufInitA(&instance->config.playerName, 0);
|
||||
}
|
||||
|
||||
void ffInitInstance(FFinstance* instance)
|
||||
@@ -254,3 +261,46 @@ void ffFinish(FFinstance* instance)
|
||||
|
||||
resetConsole(instance->config.disableLinewrap, instance->config.hideCursor);
|
||||
}
|
||||
|
||||
void ffListFeatures()
|
||||
{
|
||||
fputs(
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
"libpci\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
"vulkan\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
"wayland\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_XCB_RANDR
|
||||
"xcb-randr\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_XCB
|
||||
"xcb\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_XRANDR
|
||||
"xrandr\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_X11
|
||||
"x11\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_GIO
|
||||
"gio\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_DCONF
|
||||
"dconf\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_DBUS
|
||||
"dbus\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_XFCONF
|
||||
"xfconf\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_RPM
|
||||
"librpm\n"
|
||||
#endif
|
||||
""
|
||||
, stdout);
|
||||
}
|
||||
|
||||
@@ -133,6 +133,12 @@
|
||||
# Default is /etc/os-release.
|
||||
#--os-file /etc/os-release
|
||||
|
||||
# Player name option
|
||||
# Sets the name of the player. This is also used in song detection
|
||||
# Must be the exact name of the player or a dbus address (e.g. org.mpris.MediaPlayer2.spotify)
|
||||
# Default is the first match starting with org.mpris.MediaPlayer2.
|
||||
#--player-name spotify
|
||||
|
||||
# Key options:
|
||||
# Sets the displayed key of a module
|
||||
# Can be any string. Some of theme take an argument like a format string. See "fastfetch --help format" for help.
|
||||
@@ -162,6 +168,8 @@
|
||||
#--locale-key Locale
|
||||
#--local-ip-key Local IP ({1})
|
||||
#--public-ip-key Public IP
|
||||
#--player-key Media Player
|
||||
#--song-key Song
|
||||
|
||||
# Format options:
|
||||
# Sets the format string for module values.
|
||||
@@ -194,6 +202,8 @@
|
||||
#--locale-format
|
||||
#--local-ip-format
|
||||
#--public-ip-format
|
||||
#--player-format
|
||||
#--song-format
|
||||
|
||||
# Library options:
|
||||
# Sets an user specific path to a library to load.
|
||||
@@ -207,5 +217,6 @@
|
||||
#--lib-X11 /usr/lib/libX11.so
|
||||
#--lib-gio /usr/lib/libgio-2.0.so
|
||||
#--lib-DConf /usr/lib/libdconf.so
|
||||
#--lib-DBus /usr/lib/libdbus-1.so
|
||||
#--lib-XFConf /usr/lib/libxfconf-0.so
|
||||
#--lib-rpm /usr/lib/librpm.so
|
||||
|
||||
@@ -62,6 +62,8 @@ Format options: Provide the format string for custom output. Use fastfetch --hel
|
||||
--locale-format <format>
|
||||
--local-ip-format <format>
|
||||
--public-ip-format <format>
|
||||
--player-format <format>
|
||||
--song-format <format>
|
||||
|
||||
Key options: Provide a custom key for an output
|
||||
--os-key <key>
|
||||
@@ -90,6 +92,8 @@ Key options: Provide a custom key for an output
|
||||
--locale-key <key>
|
||||
--local-ip-key <key>: takes the name of this network interface as format argument
|
||||
--public-ip-key <key>
|
||||
--player-key <key>
|
||||
--song-key <key>
|
||||
|
||||
Library options: Set the path of a library to load
|
||||
--lib-PCI <path>
|
||||
@@ -101,6 +105,7 @@ Library options: Set the path of a library to load
|
||||
--lib-X11 <path>
|
||||
--lib-gio <path>
|
||||
--lib-DConf <path>
|
||||
--lib-DBus <path>
|
||||
--lib-XFConf <path>
|
||||
--lib-RPM <path>
|
||||
|
||||
@@ -113,6 +118,7 @@ Module specific options:
|
||||
--localip-show-ipv6 <?value>: Show ipv6 addresses in local ip module. Default is false
|
||||
--localip-show-loop <?value>: Show loop back addresses (127.0.0.1) in local ip module. Default is false
|
||||
--public-ip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
|
||||
--player-name: The name of the player to use
|
||||
|
||||
Parsing is not case sensitive. E.g. "--lib-PCI" is equal to "--Lib-Pci"
|
||||
If a value starts with a ?, it is optional. "true" will be used if not set.
|
||||
|
||||
@@ -16,11 +16,13 @@ LocalIP
|
||||
Memory
|
||||
OS
|
||||
Packages
|
||||
Player
|
||||
Processes
|
||||
PublicIP
|
||||
Resolution
|
||||
Separator
|
||||
Shell
|
||||
Song
|
||||
Terminal
|
||||
TerminalFont
|
||||
Theme
|
||||
|
||||
@@ -0,0 +1,306 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef FF_HAVE_DBUS
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
#define FF_DBUS_MPRIS_PREFIX "org.mpris.MediaPlayer2."
|
||||
|
||||
#define FF_DBUS_ITER_CONTINUE(iterator) \
|
||||
{ \
|
||||
if(!data->ffdbus_message_iter_has_next(&iterator)) \
|
||||
break; \
|
||||
data->ffdbus_message_iter_next(&iterator); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
typedef struct DBusData
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(dbus_message_new_method_call)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_init)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_init_append)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_append_basic)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_get_arg_type)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_get_basic)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_recurse)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_has_next)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_next)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_unref)
|
||||
FF_LIBRARY_SYMBOL(dbus_connection_send_with_reply)
|
||||
FF_LIBRARY_SYMBOL(dbus_connection_flush)
|
||||
FF_LIBRARY_SYMBOL(dbus_pending_call_block)
|
||||
FF_LIBRARY_SYMBOL(dbus_pending_call_steal_reply)
|
||||
FF_LIBRARY_SYMBOL(dbus_pending_call_unref)
|
||||
|
||||
DBusConnection *connection;
|
||||
} DBusData;
|
||||
|
||||
static void getString(DBusMessageIter* iter, FFstrbuf* result, DBusData* data)
|
||||
{
|
||||
if(data->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
|
||||
return;
|
||||
|
||||
const char* value;
|
||||
data->ffdbus_message_iter_get_basic(iter, &value);
|
||||
ffStrbufAppendS(result, value);
|
||||
}
|
||||
|
||||
static void getArray(DBusMessageIter* iter, FFstrbuf* result, DBusData* data)
|
||||
{
|
||||
if(data->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
|
||||
return;
|
||||
|
||||
DBusMessageIter arrayIter;
|
||||
data->ffdbus_message_iter_recurse(iter, &arrayIter);
|
||||
|
||||
while(true)
|
||||
{
|
||||
getString(&arrayIter, result, data);
|
||||
ffStrbufAppendS(result, ", ");
|
||||
|
||||
FF_DBUS_ITER_CONTINUE(arrayIter);
|
||||
}
|
||||
|
||||
if(ffStrbufEndsWithS(result, ", "))
|
||||
ffStrbufSubstrBefore(result, result->length - 2);
|
||||
}
|
||||
|
||||
static bool detectSong(const char* player, FFMediaResult* result, DBusData* data)
|
||||
{
|
||||
DBusMessage* message = data->ffdbus_message_new_method_call(player, "/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties", "Get");
|
||||
if(message == NULL)
|
||||
return false;
|
||||
|
||||
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))
|
||||
{
|
||||
data->ffdbus_message_unref(message);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* arg2 = "Metadata";
|
||||
if(!data->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &arg2))
|
||||
{
|
||||
data->ffdbus_message_unref(message);
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
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)
|
||||
return false;
|
||||
|
||||
DBusMessageIter variantIterator;
|
||||
data->ffdbus_message_iter_recurse(&rootIterator, &variantIterator);
|
||||
if(data->ffdbus_message_iter_get_arg_type(&variantIterator) != DBUS_TYPE_ARRAY)
|
||||
return false;
|
||||
|
||||
DBusMessageIter arrayIterator;
|
||||
data->ffdbus_message_iter_recurse(&variantIterator, &arrayIterator);
|
||||
|
||||
while(true)
|
||||
{
|
||||
if(data->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_DICT_ENTRY)
|
||||
FF_DBUS_ITER_CONTINUE(arrayIterator)
|
||||
|
||||
DBusMessageIter dictIterator;
|
||||
data->ffdbus_message_iter_recurse(&arrayIterator, &dictIterator);
|
||||
|
||||
if(data->ffdbus_message_iter_get_arg_type(&dictIterator) != DBUS_TYPE_STRING)
|
||||
FF_DBUS_ITER_CONTINUE(arrayIterator)
|
||||
|
||||
const char* key;
|
||||
data->ffdbus_message_iter_get_basic(&dictIterator, &key);
|
||||
|
||||
if(!data->ffdbus_message_iter_has_next(&dictIterator))
|
||||
FF_DBUS_ITER_CONTINUE(arrayIterator)
|
||||
|
||||
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)
|
||||
getString(&valueIter, &result->song, data);
|
||||
else if(strcmp(key, "xesam:album") == 0)
|
||||
getString(&valueIter, &result->album, data);
|
||||
else if(strcmp(key, "xesam:artist") == 0)
|
||||
getArray(&valueIter, &result->artist, data);
|
||||
|
||||
if(result->song.length > 0 && result->artist.length > 0 && result->album.length > 0)
|
||||
break;
|
||||
|
||||
FF_DBUS_ITER_CONTINUE(arrayIterator)
|
||||
}
|
||||
|
||||
if(result->song.length == 0)
|
||||
{
|
||||
ffStrbufClear(&result->artist);
|
||||
ffStrbufClear(&result->album);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void getCustomPlayer(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);
|
||||
return;
|
||||
}
|
||||
|
||||
FFstrbuf busName;
|
||||
ffStrbufInit(&busName);
|
||||
ffStrbufAppendS(&busName, FF_DBUS_MPRIS_PREFIX);
|
||||
ffStrbufAppend(&busName, &instance->config.playerName);
|
||||
detectSong(busName.chars, result, data);
|
||||
ffStrbufDestroy(&busName);
|
||||
|
||||
ffStrbufAppend(&result->player, &instance->config.playerName);
|
||||
}
|
||||
|
||||
static void getBestPlayer(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)
|
||||
return;
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
if(reply == NULL)
|
||||
return;
|
||||
|
||||
DBusMessageIter rootIterator;
|
||||
if(!data->ffdbus_message_iter_init(reply, &rootIterator) || data->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_ARRAY)
|
||||
return;
|
||||
|
||||
DBusMessageIter arrayIterator;
|
||||
data->ffdbus_message_iter_recurse(&rootIterator, &arrayIterator);
|
||||
|
||||
while(true)
|
||||
{
|
||||
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);
|
||||
|
||||
if(strncmp(name, FF_DBUS_MPRIS_PREFIX, sizeof(FF_DBUS_MPRIS_PREFIX) - 1) != 0)
|
||||
FF_DBUS_ITER_CONTINUE(arrayIterator)
|
||||
|
||||
if(detectSong(name, result, data))
|
||||
{
|
||||
ffStrbufAppendS(&result->player, name + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
FF_DBUS_ITER_CONTINUE(arrayIterator)
|
||||
}
|
||||
}
|
||||
|
||||
static void getMedia(FFinstance* instance, FFMediaResult* result)
|
||||
{
|
||||
DBusData data;
|
||||
|
||||
FF_LIBRARY_LOAD(dbus, instance->config.libDBus, , "libdbus-1.so", "libdbus-1.so.3");
|
||||
FF_LIBRARY_LOAD_SYMBOL(dbus, dbus_bus_get,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_new_method_call, dbus_message_new_method_call,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_iter_init, dbus_message_iter_init,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_iter_init_append, dbus_message_iter_init_append,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_iter_append_basic, dbus_message_iter_append_basic,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_iter_get_arg_type, dbus_message_iter_get_arg_type,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_iter_get_basic, dbus_message_iter_get_basic,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_iter_recurse, dbus_message_iter_recurse,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_iter_has_next, dbus_message_iter_has_next,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_iter_next, dbus_message_iter_next,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_message_unref, dbus_message_unref,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_connection_send_with_reply, dbus_connection_send_with_reply,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_connection_flush, dbus_connection_flush,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_pending_call_block, dbus_pending_call_block,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_pending_call_steal_reply, dbus_pending_call_steal_reply,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(dbus, data.ffdbus_pending_call_unref, dbus_pending_call_unref,)
|
||||
|
||||
data.connection = ffdbus_bus_get(DBUS_BUS_SESSION, NULL);
|
||||
if(data.connection == NULL)
|
||||
{
|
||||
dlclose(dbus);
|
||||
return;
|
||||
}
|
||||
|
||||
if(instance->config.playerName.length > 0)
|
||||
getCustomPlayer(instance, result, &data);
|
||||
else
|
||||
getBestPlayer(result, &data);
|
||||
|
||||
dlclose(dbus);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const FFMediaResult* ffDetectMedia(FFinstance* instance)
|
||||
{
|
||||
static FFMediaResult result;
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static bool init = false;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
if(init)
|
||||
{
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
init = true;
|
||||
|
||||
ffStrbufInit(&result.player);
|
||||
ffStrbufInit(&result.song);
|
||||
ffStrbufInit(&result.artist);
|
||||
ffStrbufInit(&result.album);
|
||||
|
||||
#ifdef FF_HAVE_DBUS
|
||||
getMedia(instance, &result);
|
||||
#endif
|
||||
|
||||
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);
|
||||
else
|
||||
ffStrbufAppend(&result.player, &instance->config.playerName);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
+31
-41
@@ -302,6 +302,20 @@ static inline void printCommandHelp(const char* command)
|
||||
"Public IP address"
|
||||
);
|
||||
}
|
||||
else if(strcasecmp(command, "player-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("player", "{}", 1,
|
||||
"Player name"
|
||||
);
|
||||
}
|
||||
else if(strcasecmp(command, "song-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("song", "{2} - {3} - {1}", 3,
|
||||
"Song name",
|
||||
"Artist name",
|
||||
"Album name"
|
||||
);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "No specific help for command %s provided\n", command);
|
||||
}
|
||||
@@ -358,46 +372,6 @@ static inline void listAvailablePresets(FFinstance* instance)
|
||||
ffStrbufDestroy(&folder);
|
||||
}
|
||||
|
||||
static inline void listSupportedFeatures()
|
||||
{
|
||||
fputs(
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
"libpci\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
"vulkan\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
"wayland\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_XCB_RANDR
|
||||
"xcb-randr\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_XCB
|
||||
"xcb\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_XRANDR
|
||||
"xrandr\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_X11
|
||||
"x11\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_GIO
|
||||
"gio\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_DCONF
|
||||
"dconf\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_XFCONF
|
||||
"xfconf\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_RPM
|
||||
"librpm\n"
|
||||
#endif
|
||||
""
|
||||
, stdout);
|
||||
}
|
||||
|
||||
static void parseOption(FFinstance* instance, FFdata* data, const char* key, const char* value);
|
||||
|
||||
static void parseConfigFile(FFinstance* instance, FFdata* data, FILE* file)
|
||||
@@ -654,7 +628,7 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
}
|
||||
else if(strcasecmp(key, "--list-features") == 0)
|
||||
{
|
||||
listSupportedFeatures();
|
||||
ffListFeatures();
|
||||
exit(0);
|
||||
}
|
||||
else if(strcasecmp(key, "--spacing") == 0)
|
||||
@@ -844,6 +818,14 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
optionParseString(key, value, &instance->config.publicIpKey);
|
||||
else if(strcasecmp(key, "--public-ip-format") == 0)
|
||||
optionParseString(key, value, &instance->config.publicIpFormat);
|
||||
else if(strcasecmp(key, "--player-key") == 0)
|
||||
optionParseString(key, value, &instance->config.playerKey);
|
||||
else if(strcasecmp(key, "--player-format") == 0)
|
||||
optionParseString(key, value, &instance->config.playerFormat);
|
||||
else if(strcasecmp(key, "--song-key") == 0)
|
||||
optionParseString(key, value, &instance->config.songKey);
|
||||
else if(strcasecmp(key, "--song-format") == 0)
|
||||
optionParseString(key, value, &instance->config.songFormat);
|
||||
else if(strcasecmp(key, "--lib-PCI") == 0)
|
||||
optionParseString(key, value, &instance->config.libPCI);
|
||||
else if(strcasecmp(key, "--lib-vulkan") == 0)
|
||||
@@ -862,6 +844,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
optionParseString(key, value, &instance->config.libGIO);
|
||||
else if(strcasecmp(key, "--lib-DConf") == 0)
|
||||
optionParseString(key, value, &instance->config.libDConf);
|
||||
else if(strcasecmp(key, "--lib-dbus") == 0)
|
||||
optionParseString(key, value, &instance->config.libDBus);
|
||||
else if(strcasecmp(key, "--lib-XFConf") == 0)
|
||||
optionParseString(key, value, &instance->config.libXFConf);
|
||||
else if(strcasecmp(key, "--lib-rpm") == 0)
|
||||
@@ -880,6 +864,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
instance->config.localIpShowLoop = optionParseBoolean(value);
|
||||
else if(strcasecmp(key, "--os-file") == 0)
|
||||
optionParseString(key, value, &instance->config.osFile);
|
||||
else if(strcasecmp(key, "--player-name") == 0)
|
||||
optionParseString(key, value, &instance->config.playerName);
|
||||
else if(strcasecmp(key, "--public-ip-timeout") == 0)
|
||||
{
|
||||
if(value == NULL)
|
||||
@@ -1032,6 +1018,10 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char
|
||||
ffPrintLocalIp(instance);
|
||||
else if(strcasecmp(line, "publicip") == 0)
|
||||
ffPrintPublicIp(instance);
|
||||
else if(strcasecmp(line, "player") == 0)
|
||||
ffPrintPlayer(instance);
|
||||
else if(strcasecmp(line, "song") == 0)
|
||||
ffPrintSong(instance);
|
||||
else if(strcasecmp(line, "colors") == 0)
|
||||
ffPrintColors(instance);
|
||||
else
|
||||
|
||||
@@ -110,6 +110,10 @@ typedef struct FFconfig
|
||||
FFstrbuf localIpFormat;
|
||||
FFstrbuf publicIpKey;
|
||||
FFstrbuf publicIpFormat;
|
||||
FFstrbuf playerKey;
|
||||
FFstrbuf playerFormat;
|
||||
FFstrbuf songKey;
|
||||
FFstrbuf songFormat;
|
||||
|
||||
FFstrbuf libPCI;
|
||||
FFstrbuf libVulkan;
|
||||
@@ -120,6 +124,7 @@ typedef struct FFconfig
|
||||
FFstrbuf libX11;
|
||||
FFstrbuf libGIO;
|
||||
FFstrbuf libDConf;
|
||||
FFstrbuf libDBus;
|
||||
FFstrbuf libXFConf;
|
||||
FFstrbuf librpm;
|
||||
|
||||
@@ -137,6 +142,7 @@ typedef struct FFconfig
|
||||
|
||||
FFstrbuf osFile;
|
||||
|
||||
FFstrbuf playerName;
|
||||
} FFconfig;
|
||||
|
||||
typedef struct FFstate
|
||||
@@ -243,6 +249,14 @@ typedef struct FFTempsResult
|
||||
FFlist values; //List of FFTempValue
|
||||
} FFTempsResult;
|
||||
|
||||
typedef struct FFMediaResult
|
||||
{
|
||||
FFstrbuf player;
|
||||
FFstrbuf song;
|
||||
FFstrbuf artist;
|
||||
FFstrbuf album;
|
||||
} FFMediaResult;
|
||||
|
||||
typedef enum FFformatargtype
|
||||
{
|
||||
FF_FORMAT_ARG_TYPE_NULL = 0,
|
||||
@@ -337,6 +351,8 @@ void ffInitInstance(FFinstance* instance);
|
||||
void ffStart(FFinstance* instance);
|
||||
void ffFinish(FFinstance* instance);
|
||||
|
||||
void ffListFeatures();
|
||||
|
||||
//common/threading.c
|
||||
void ffStartDetectionThreads(FFinstance* instance);
|
||||
|
||||
@@ -447,6 +463,9 @@ const FFTerminalShellResult* ffDetectTerminalShell(FFinstance* instance);
|
||||
//detection/temps.c (currently unused)
|
||||
const FFTempsResult* ffDetectTemps(const FFinstance* instance);
|
||||
|
||||
//detection/media.c
|
||||
const FFMediaResult* ffDetectMedia(FFinstance* instance);
|
||||
|
||||
/********************/
|
||||
/* Module functions */
|
||||
/********************/
|
||||
@@ -486,6 +505,8 @@ void ffPrintBattery(FFinstance* instance);
|
||||
void ffPrintLocale(FFinstance* instance);
|
||||
void ffPrintLocalIp(FFinstance* instance);
|
||||
void ffPrintPublicIp(FFinstance* instance);
|
||||
void ffPrintPlayer(FFinstance* instance);
|
||||
void ffPrintSong(FFinstance* instance);
|
||||
void ffPrintColors(FFinstance* instance);
|
||||
|
||||
#endif
|
||||
|
||||
+3
-1
@@ -26,7 +26,7 @@ int main(int argc, char** argv)
|
||||
ffPrintHost(&instance);
|
||||
ffPrintKernel(&instance);
|
||||
ffPrintUptime(&instance);
|
||||
ffPrintProcesses(&instance);
|
||||
//ffPrintProcesses(&instance);
|
||||
ffPrintPackages(&instance);
|
||||
ffPrintShell(&instance);
|
||||
ffPrintResolution(&instance);
|
||||
@@ -47,6 +47,8 @@ int main(int argc, char** argv)
|
||||
ffPrintBattery(&instance);
|
||||
//ffPrintLocalIp(&instance);
|
||||
//ffPrintPublicIp(&instance);
|
||||
//ffPrintPlayer(&instance);
|
||||
//ffPrintSong(&instance);
|
||||
ffPrintLocale(&instance);
|
||||
ffPrintBreak(&instance);
|
||||
ffPrintColors(&instance);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_PLAYER_MODULE_NAME "Media Player"
|
||||
#define FF_PLAYER_NUM_FORMAT_ARGS 1
|
||||
|
||||
void ffPrintPlayer(FFinstance* instance)
|
||||
{
|
||||
const FFMediaResult* media = ffDetectMedia(instance);
|
||||
|
||||
if(media->player.length == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_PLAYER_MODULE_NAME, 0, &instance->config.playerKey, &instance->config.playerFormat, FF_PLAYER_NUM_FORMAT_ARGS, "No media player found");
|
||||
return;
|
||||
}
|
||||
|
||||
if(instance->config.playerFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, FF_PLAYER_MODULE_NAME, 0, &instance->config.playerKey);
|
||||
ffStrbufPutTo(&media->player, stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormatString(instance, FF_PLAYER_MODULE_NAME, 0, &instance->config.playerKey, &instance->config.playerFormat, NULL, FF_PLAYER_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &media->player}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_SONG_MODULE_NAME "Song"
|
||||
#define FF_SONG_NUM_FORMAT_ARGS 3
|
||||
|
||||
void ffPrintSong(FFinstance* instance)
|
||||
{
|
||||
const FFMediaResult* media = ffDetectMedia(instance);
|
||||
|
||||
if(media->song.length == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_SONG_MODULE_NAME, 0, &instance->config.songKey, &instance->config.songFormat, FF_SONG_NUM_FORMAT_ARGS, "No song detected");
|
||||
return;
|
||||
}
|
||||
|
||||
if(instance->config.songFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, FF_SONG_MODULE_NAME, 0, &instance->config.songKey);
|
||||
|
||||
if(media->artist.length > 0)
|
||||
{
|
||||
ffStrbufWriteTo(&media->artist, stdout);
|
||||
fputs(" - ", stdout);
|
||||
}
|
||||
|
||||
if(media->album.length > 0)
|
||||
{
|
||||
ffStrbufWriteTo(&media->album, stdout);
|
||||
fputs(" - ", stdout);
|
||||
}
|
||||
|
||||
ffStrbufPutTo(&media->song, stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormatString(instance, FF_SONG_MODULE_NAME, 0, &instance->config.songKey, &instance->config.songFormat, NULL, FF_SONG_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &media->song},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &media->artist},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &media->album}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user