Skip to content

Commit

Permalink
Bluetooth (Linux): improve performance
Browse files Browse the repository at this point in the history
1. ignore unpaired devices
2. ignore disconnected devices when `showDisconnected == false`
  • Loading branch information
CarterLi committed Dec 20, 2024
1 parent c5d4b20 commit 74586a9
Showing 1 changed file with 55 additions and 29 deletions.
84 changes: 55 additions & 29 deletions src/detection/bluetooth/bluetooth_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,16 @@ array [ //root
]
*/

static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device)
static bool detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
return true;

DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);

if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
return;
return true;

const char* deviceProperty;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &deviceProperty);
Expand All @@ -75,6 +75,13 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue
}
else if(ffStrEquals(deviceProperty, "Connected"))
ffDBusGetBool(dbus, &dictIter, &device->connected);
else if(ffStrEquals(deviceProperty, "Paired"))
{
bool paired = true;
ffDBusGetBool(dbus, &dictIter, &paired);
if (!paired) return false;
}
return true;
}

static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device)
Expand Down Expand Up @@ -104,32 +111,37 @@ static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFB

do
{
detectBluetoothValue(dbus, &arrayIter, device);
bool shouldContinue = detectBluetoothValue(dbus, &arrayIter, device);
if (!shouldContinue)
{
ffStrbufClear(&device->name);
break;
}
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
}

static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
static FFBluetoothResult* detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
return NULL;

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;
return NULL;

const char* objectPath;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath);

// We don't want adapter objects
if(!ffStrContains(objectPath, "/dev_"))
return;
return NULL;

dbus->lib->ffdbus_message_iter_next(&dictIter);

if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
return;
return NULL;

DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
Expand All @@ -146,16 +158,10 @@ static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessage
detectBluetoothProperty(dbus, &arrayIter, device);
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));

if(device->name.length == 0)
{
ffStrbufDestroy(&device->name);
ffStrbufDestroy(&device->address);
ffStrbufDestroy(&device->type);
--devices->length;
}
return device;
}

static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter, int32_t connectedCount)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
return;
Expand All @@ -165,11 +171,25 @@ static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIt

do
{
detectBluetoothObject(devices, dbus, &arrayIter);
FFBluetoothResult* device = detectBluetoothObject(devices, dbus, &arrayIter);

if (device)
{
if(device->name.length == 0 || (connectedCount > 0 && !device->connected))
{
ffStrbufDestroy(&device->name);
ffStrbufDestroy(&device->address);
ffStrbufDestroy(&device->type);
--devices->length;
}

if (device->connected && --connectedCount == 0)
break;
}
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
}

static const char* detectBluetooth(FFlist* devices)
static const char* detectBluetooth(FFlist* devices, int32_t connectedCount)
{
FFDBusData dbus;
const char* error = ffDBusLoadData(DBUS_BUS_SYSTEM, &dbus);
Expand All @@ -187,37 +207,43 @@ static const char* detectBluetooth(FFlist* devices)
return "Failed to get root iterator of GetManagedObjects";
}

detectBluetoothRoot(devices, &dbus, &rootIter);
detectBluetoothRoot(devices, &dbus, &rootIter, connectedCount);

dbus.lib->ffdbus_message_unref(managedObjects);
return NULL;
}

static bool hasConnectedDevices(void)
static uint32_t connectedDevices(void)
{
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/bluetooth");
if(dirp == NULL)
return false;
return 0;

uint32_t result = 0;
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (strchr(entry->d_name, ':') != NULL) // ignore connected devices
return true;
if (strchr(entry->d_name, ':') != NULL)
++result;
}

return false;
return result;
}

#endif

const char* ffDetectBluetooth(FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
{
#ifdef FF_HAVE_DBUS
if (!options->showDisconnected && !hasConnectedDevices())
return NULL;

return detectBluetooth(devices);
int32_t connectedCount = -1;
if (!options->showDisconnected)
{
connectedCount = (int32_t) connectedDevices();
if (connectedCount == 0)
return NULL;
}

return detectBluetooth(devices, connectedCount);
#else
return "Fastfetch was compiled without DBus support";
#endif
Expand Down

0 comments on commit 74586a9

Please sign in to comment.