mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
Bluetooth: Support multiple devices
This commit is contained in:
@@ -199,6 +199,7 @@ __fastfetch_completion()
|
||||
"--gpu-hide-integrated"
|
||||
"--gpu-hide-discrete"
|
||||
"--disk-show-unknown"
|
||||
"--bluetooth-show-disconnected"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_STRING=(
|
||||
|
||||
@@ -160,6 +160,8 @@ static void defaultConfig(FFinstance* instance)
|
||||
instance->config.diskShowUnknown = false;
|
||||
instance->config.diskShowSubvolumes = false;
|
||||
|
||||
instance->config.bluetoothShowDisconnected = false;
|
||||
|
||||
ffStrbufInitA(&instance->config.batteryDir, 0);
|
||||
|
||||
ffStrbufInitA(&instance->config.separatorString, 0);
|
||||
|
||||
@@ -247,6 +247,12 @@
|
||||
# Default is "/:/home" ("C:\\;D:\\ ..." on Windows).
|
||||
#--disk-folders /:/home
|
||||
|
||||
# Bluetooth show disconnected option
|
||||
# Sets if disconnected bluetooth devices should be printed
|
||||
# Must be either true or false
|
||||
# Default is false.
|
||||
#--bluetooth-show-disconnected false
|
||||
|
||||
# Percentage output type option
|
||||
# Applies to all modules that prints percentage values. Currently memory, swap, disk, battery and CPU usage are supported.
|
||||
# Only works with default format ( without --module-format option ).
|
||||
|
||||
+31
-30
@@ -100,36 +100,37 @@ Library options: Set the path of a library to load
|
||||
--lib-cjson <path>
|
||||
|
||||
Module specific options:
|
||||
--title-fqdn <?value>: Set if the title should use fully qualified domain name. Default is false
|
||||
--separator-string <str>: Set the string printed by the separator module
|
||||
--os-file <path>: Set the path to the file containing OS information
|
||||
--shell-version <?value>: Set if shell version should be detected and printed
|
||||
--terminal-version <?value>: Set if terminal version should be detected and printed
|
||||
--disk-folders <folders>: A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows)
|
||||
--disk-show-removable <?value>: Set if removable volume should be printed. Default is true
|
||||
--disk-show-hidden <?value>: Set if hidden volumes should be printed. Default is false
|
||||
--disk-show-subvolumes <?value>: Set if subvolumes should be printed. Default is false
|
||||
--disk-show-unknown <?value>: Set if unknown (unable to detect sizes) volumes should be printed. Default is false
|
||||
--battery-dir <folder>: The directory where the battery folders are. Standard: /sys/class/power_supply/
|
||||
--cpu-temp <?value>: Detect and display CPU temperature if supported. Default is false
|
||||
--gpu-temp <?value>: Detect and display GPU temperature if supported. Default is false
|
||||
--gpu-hide-integrated <?value>: Hide integrated GPU if supported. Default is false
|
||||
--gpu-hide-discrete <?value>: Hide discrete GPU if supported. Default is false
|
||||
--battery-temp <?value>: Detect and display Battery temperature if supported. Default is false
|
||||
--localip-show-ipv4 <?value>: Show IPv4 addresses in local ip module. Default is true
|
||||
--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
|
||||
--localip-name-prefix <str>: Show IPs with given name prefix only. Default is empty
|
||||
--public-ip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
|
||||
--public-ip-url: The URL of public IP detection server to be used.
|
||||
--weather-timeout: Time in milliseconds to wait for the weather server to respond. Default is disabled (0)
|
||||
--weather-output-format: The output weather format to be used. It must be URI encoded.
|
||||
--player-name: The name of the player to use
|
||||
--gl <value>: Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto
|
||||
--percent-type <value>: Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only. Default is 1
|
||||
--command-shell <str>: Set the shell program to execute the command text. Default is cmd for Windows, csh for FreeBSD, bash for others
|
||||
--command-key <str>: Set the module key to display, can be specified mulitple times
|
||||
--command-text <str>: Set the command text to be executed, can be specified mulitple times
|
||||
--title-fqdn <?value>: Set if the title should use fully qualified domain name. Default is false
|
||||
--separator-string <str>: Set the string printed by the separator module
|
||||
--os-file <path>: Set the path to the file containing OS information
|
||||
--shell-version <?value>: Set if shell version should be detected and printed
|
||||
--terminal-version <?value>: Set if terminal version should be detected and printed
|
||||
--disk-folders <folders>: A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows)
|
||||
--disk-show-removable <?value>: Set if removable volume should be printed. Default is true
|
||||
--disk-show-hidden <?value>: Set if hidden volumes should be printed. Default is false
|
||||
--disk-show-subvolumes <?value>: Set if subvolumes should be printed. Default is false
|
||||
--disk-show-unknown <?value>: Set if unknown (unable to detect sizes) volumes should be printed. Default is false
|
||||
--bluetooth-show-disconnected: <?value>: Set if disconnected bluetooth devices should be printed. Default is false
|
||||
--battery-dir <folder>: The directory where the battery folders are. Standard: /sys/class/power_supply/
|
||||
--cpu-temp <?value>: Detect and display CPU temperature if supported. Default is false
|
||||
--gpu-temp <?value>: Detect and display GPU temperature if supported. Default is false
|
||||
--gpu-hide-integrated <?value>: Hide integrated GPU if supported. Default is false
|
||||
--gpu-hide-discrete <?value>: Hide discrete GPU if supported. Default is false
|
||||
--battery-temp <?value>: Detect and display Battery temperature if supported. Default is false
|
||||
--localip-show-ipv4 <?value>: Show IPv4 addresses in local ip module. Default is true
|
||||
--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
|
||||
--localip-name-prefix <str>: Show IPs with given name prefix only. Default is empty
|
||||
--public-ip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
|
||||
--public-ip-url: The URL of public IP detection server to be used.
|
||||
--weather-timeout: Time in milliseconds to wait for the weather server to respond. Default is disabled (0)
|
||||
--weather-output-format: The output weather format to be used. It must be URI encoded.
|
||||
--player-name: The name of the player to use
|
||||
--gl <value>: Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto
|
||||
--percent-type <value>: Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only. Default is 1
|
||||
--command-shell <str>: Set the shell program to execute the command text. Default is cmd for Windows, csh for FreeBSD, bash for others
|
||||
--command-key <str>: Set the module key to display, can be specified mulitple times
|
||||
--command-text <str>: Set the command text to be executed, can be specified mulitple times
|
||||
|
||||
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.
|
||||
|
||||
@@ -8,14 +8,8 @@ const FFBluetoothResult* ffDetectBluetooth(const FFinstance* instance)
|
||||
{
|
||||
FF_DETECTION_INTERNAL_GUARD(FFBluetoothResult,
|
||||
ffStrbufInit(&result.error);
|
||||
ffStrbufInit(&result.name);
|
||||
ffStrbufInit(&result.address);
|
||||
ffStrbufInit(&result.type);
|
||||
result.battery = 0;
|
||||
ffListInit(&result.devices, sizeof(FFBluetoothDevice));
|
||||
|
||||
ffDetectBluetoothImpl(instance, &result);
|
||||
|
||||
if(result.error.length == 0 && result.name.length == 0)
|
||||
ffStrbufAppendS(&result.error, "No bluetooth device found");
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,13 +5,19 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFBluetoothResult
|
||||
typedef struct FFBluetoothDevice
|
||||
{
|
||||
FFstrbuf error;
|
||||
FFstrbuf name;
|
||||
FFstrbuf address;
|
||||
FFstrbuf type;
|
||||
uint8_t battery; // 0-100%
|
||||
bool connected;
|
||||
} FFBluetoothDevice;
|
||||
|
||||
typedef struct FFBluetoothResult
|
||||
{
|
||||
FFstrbuf error;
|
||||
FFlist devices; // List of FFBluetoothDevice
|
||||
} FFBluetoothResult;
|
||||
|
||||
const FFBluetoothResult* ffDetectBluetooth(const FFinstance* instance);
|
||||
|
||||
@@ -39,7 +39,7 @@ array [ //root
|
||||
]
|
||||
*/
|
||||
|
||||
static void detectBluetoothProperty(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter, bool* connected)
|
||||
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothDevice* device)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
|
||||
return;
|
||||
@@ -81,68 +81,66 @@ static void detectBluetoothProperty(FFBluetoothResult* bluetooth, FFDBusData* db
|
||||
dbus->lib->ffdbus_message_iter_next(&deviceIter);
|
||||
|
||||
if(strcmp(deviceProperty, "Address") == 0)
|
||||
ffDBusGetValue(dbus, &deviceIter, &bluetooth->address);
|
||||
ffDBusGetValue(dbus, &deviceIter, &device->address);
|
||||
else if(strcmp(deviceProperty, "Name") == 0)
|
||||
ffDBusGetValue(dbus, &deviceIter, &bluetooth->name);
|
||||
ffDBusGetValue(dbus, &deviceIter, &device->name);
|
||||
else if(strcmp(deviceProperty, "Icon") == 0)
|
||||
ffDBusGetValue(dbus, &deviceIter, &bluetooth->type);
|
||||
ffDBusGetValue(dbus, &deviceIter, &device->type);
|
||||
else if(strcmp(deviceProperty, "Percentage") == 0)
|
||||
ffDBusGetByte(dbus, &deviceIter, &bluetooth->battery);
|
||||
ffDBusGetByte(dbus, &deviceIter, &device->battery);
|
||||
else if(strcmp(deviceProperty, "Connected") == 0)
|
||||
{
|
||||
ffDBusGetBool(dbus, &deviceIter, connected);
|
||||
if(!*connected)
|
||||
return; //Just for performance, we don't need to continue if we're not connected
|
||||
}
|
||||
ffDBusGetBool(dbus, &deviceIter, &device->connected);
|
||||
|
||||
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
|
||||
}
|
||||
}
|
||||
|
||||
static bool detectBluetoothObject(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter)
|
||||
static void detectBluetoothObject(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
|
||||
return false;
|
||||
return;
|
||||
|
||||
DBusMessageIter dictIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_OBJECT_PATH)
|
||||
return false;
|
||||
return;
|
||||
|
||||
const char* objectPath;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath);
|
||||
|
||||
//We don't want adapter objects
|
||||
if(strstr(objectPath, "dev_") == NULL)
|
||||
return false;
|
||||
return;
|
||||
|
||||
dbus->lib->ffdbus_message_iter_next(&dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
|
||||
return false;
|
||||
return;
|
||||
|
||||
DBusMessageIter arrayIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
|
||||
|
||||
bool connected = false;
|
||||
FFBluetoothDevice* device = ffListAdd(&bluetooth->devices);
|
||||
ffStrbufInit(&device->name);
|
||||
ffStrbufInit(&device->address);
|
||||
ffStrbufInit(&device->type);
|
||||
device->battery = 0;
|
||||
device->connected = false;
|
||||
|
||||
while(true)
|
||||
{
|
||||
detectBluetoothProperty(bluetooth, dbus, &arrayIter, &connected);
|
||||
detectBluetoothProperty(dbus, &arrayIter, device);
|
||||
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
|
||||
}
|
||||
|
||||
if(!connected || bluetooth->name.length == 0)
|
||||
if(device->name.length == 0)
|
||||
{
|
||||
ffStrbufClear(&bluetooth->address);
|
||||
ffStrbufClear(&bluetooth->name);
|
||||
ffStrbufClear(&bluetooth->type);
|
||||
bluetooth->battery = 0;
|
||||
return false;
|
||||
ffStrbufDestroy(&device->name);
|
||||
ffStrbufDestroy(&device->address);
|
||||
ffStrbufDestroy(&device->type);
|
||||
--bluetooth->devices.length;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void detectBluetoothRoot(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter)
|
||||
@@ -155,9 +153,7 @@ static void detectBluetoothRoot(FFBluetoothResult* bluetooth, FFDBusData* dbus,
|
||||
|
||||
while(true)
|
||||
{
|
||||
if(detectBluetoothObject(bluetooth, dbus, &arrayIter))
|
||||
return;
|
||||
|
||||
detectBluetoothObject(bluetooth, dbus, &arrayIter);
|
||||
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
|
||||
}
|
||||
|
||||
|
||||
@@ -1310,6 +1310,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
instance->config.diskShowSubvolumes = optionParseBoolean(value);
|
||||
else if(strcasecmp(key, "--disk-show-unknown") == 0)
|
||||
instance->config.diskShowUnknown = optionParseBoolean(value);
|
||||
else if(strcasecmp(key, "--bluetooth-show-disconnected") == 0)
|
||||
instance->config.bluetoothShowDisconnected = optionParseBoolean(value);
|
||||
else if(strcasecmp(key, "--battery-dir") == 0)
|
||||
optionParseString(key, value, &instance->config.batteryDir);
|
||||
else if(strcasecmp(key, "--separator-string") == 0)
|
||||
|
||||
@@ -184,6 +184,8 @@ typedef struct FFconfig
|
||||
bool diskShowUnknown;
|
||||
bool diskShowSubvolumes;
|
||||
|
||||
bool bluetoothShowDisconnected;
|
||||
|
||||
FFstrbuf batteryDir;
|
||||
|
||||
FFstrbuf separatorString;
|
||||
|
||||
+40
-14
@@ -4,6 +4,29 @@
|
||||
#define FF_BLUETOOTH_MODULE_NAME "Bluetooth"
|
||||
#define FF_BLUETOOTH_NUM_FORMAT_ARGS 4
|
||||
|
||||
static void printDevice(FFinstance* instance, const FFBluetoothDevice* device, uint8_t index)
|
||||
{
|
||||
if(instance->config.bluetooth.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, FF_BLUETOOTH_MODULE_NAME, index, &instance->config.bluetooth.key);
|
||||
ffStrbufWriteTo(&device->name, stdout);
|
||||
|
||||
if(device->battery > 0)
|
||||
printf(" (%d%%)", device->battery);
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormat(instance, FF_BLUETOOTH_MODULE_NAME, index, &instance->config.bluetooth, FF_BLUETOOTH_NUM_FORMAT_ARGS, (FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &device->name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &device->address},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &device->type},
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &device->battery}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void ffPrintBluetooth(FFinstance* instance)
|
||||
{
|
||||
const FFBluetoothResult* bluetooth = ffDetectBluetooth(instance);
|
||||
@@ -14,23 +37,26 @@ void ffPrintBluetooth(FFinstance* instance)
|
||||
return;
|
||||
}
|
||||
|
||||
if(instance->config.bluetooth.outputFormat.length == 0)
|
||||
FFlist filtered;
|
||||
ffListInit(&filtered, sizeof(FFBluetoothDevice*));
|
||||
|
||||
FF_LIST_FOR_EACH(FFBluetoothDevice, device, bluetooth->devices)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, FF_BLUETOOTH_MODULE_NAME, 0, &instance->config.bluetooth.key);
|
||||
ffStrbufWriteTo(&bluetooth->name, stdout);
|
||||
if(!device->connected && !instance->config.bluetoothShowDisconnected)
|
||||
continue;
|
||||
|
||||
if(bluetooth->battery > 0)
|
||||
printf(" (%d%%)", bluetooth->battery);
|
||||
|
||||
putchar('\n');
|
||||
*(FFBluetoothDevice**)ffListAdd(&filtered) = device;
|
||||
}
|
||||
else
|
||||
|
||||
if(filtered.length == 0)
|
||||
{
|
||||
ffPrintFormat(instance, FF_BLUETOOTH_MODULE_NAME, 0, &instance->config.bluetooth, FF_BLUETOOTH_NUM_FORMAT_ARGS, (FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &bluetooth->name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &bluetooth->address},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &bluetooth->type},
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &bluetooth->battery}
|
||||
});
|
||||
ffPrintError(instance, FF_BLUETOOTH_MODULE_NAME, 0, &instance->config.bluetooth, "No bluetooth devices found");
|
||||
return;
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < filtered.length; i++)
|
||||
{
|
||||
uint8_t index = (uint8_t) (filtered.length == 1 ? 0 : i + 1);
|
||||
printDevice(instance, *(FFBluetoothDevice**)ffListGet(&filtered, i), index);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user