From 6d921617f9b5302a2e37d1942c62d9cbec94afe4 Mon Sep 17 00:00:00 2001 From: Christian Kellner Date: Wed, 10 Apr 2019 23:57:00 +0200 Subject: [PATCH 1/2] daemon: make context_num_clients a public method So it can be used from outside daemon/gamemode.c, to e.g. implement an ClientCount property. --- daemon/gamemode.c | 6 +----- daemon/gamemode.h | 7 +++++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/daemon/gamemode.c b/daemon/gamemode.c index 71f1a78..3bb8be4 100644 --- a/daemon/gamemode.c +++ b/daemon/gamemode.c @@ -89,7 +89,6 @@ static volatile bool had_context_init = false; static GameModeClient *game_mode_client_new(pid_t pid, char *exe); static void game_mode_client_free(GameModeClient *client); static const GameModeClient *game_mode_context_has_client(GameModeContext *self, pid_t client); -static int game_mode_context_num_clients(GameModeContext *self); static void *game_mode_context_reaper(void *userdata); static void game_mode_context_enter(GameModeContext *self); static void game_mode_context_leave(GameModeContext *self); @@ -316,10 +315,7 @@ static const GameModeClient *game_mode_context_has_client(GameModeContext *self, return found; } -/** - * Helper to grab the current number of clients we know about - */ -static int game_mode_context_num_clients(GameModeContext *self) +int game_mode_context_num_clients(GameModeContext *self) { return atomic_load(&self->refcount); } diff --git a/daemon/gamemode.h b/daemon/gamemode.h index 4c469ad..7a7703c 100644 --- a/daemon/gamemode.h +++ b/daemon/gamemode.h @@ -63,6 +63,13 @@ void game_mode_context_init(GameModeContext *self); */ void game_mode_context_destroy(GameModeContext *self); +/** + * Query the number of currently registered clients. + * + * @returns The number of clients. A number > 0 means that gamemode is active. + */ +int game_mode_context_num_clients(GameModeContext *self); + /** * Register a new game client with the context * From 05909d1cfa73eb134cf8af4f157d627506a1e504 Mon Sep 17 00:00:00 2001 From: Christian Kellner Date: Wed, 10 Apr 2019 23:57:27 +0200 Subject: [PATCH 2/2] daemon: add a ClientCount dbus property Introduce a new "ClientCount" dbus property that can be queried and also watched to see if gamemode is currently active (or not). --- daemon/dbus_messaging.c | 50 +++++++++++++++++++++++++++++++---------- daemon/dbus_messaging.h | 5 +++++ daemon/gamemode.c | 4 ++++ 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/daemon/dbus_messaging.c b/daemon/dbus_messaging.c index ac72c9c..0a9fe20 100644 --- a/daemon/dbus_messaging.c +++ b/daemon/dbus_messaging.c @@ -182,22 +182,48 @@ static int method_query_status_by_pid(sd_bus_message *m, void *userdata, return sd_bus_reply_method_return(m, "i", status); } +/** + * Handles the Active D-BUS Method + */ +static int property_get_client_count(sd_bus *local_bus, const char *path, const char *interface, + const char *property, sd_bus_message *reply, void *userdata, + __attribute__((unused)) sd_bus_error *ret_error) +{ + GameModeContext *context = userdata; + int count; + + count = game_mode_context_num_clients(context); + + return sd_bus_message_append_basic(reply, 'i', &count); +} + +void game_mode_client_count_changed(void) +{ + (void)sd_bus_emit_properties_changed(bus, + "/com/feralinteractive/GameMode", + "com.feralinteractive.GameMode", + "ClientCount", + NULL); +} /** * D-BUS vtable to dispatch virtual methods */ -static const sd_bus_vtable gamemode_vtable[] = - { SD_BUS_VTABLE_START(0), - SD_BUS_METHOD("RegisterGame", "i", "i", method_register_game, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("UnregisterGame", "i", "i", method_unregister_game, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("QueryStatus", "i", "i", method_query_status, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("RegisterGameByPID", "ii", "i", method_register_game_by_pid, - SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("UnregisterGameByPID", "ii", "i", method_unregister_game_by_pid, - SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("QueryStatusByPID", "ii", "i", method_query_status_by_pid, - SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_VTABLE_END }; +static const sd_bus_vtable gamemode_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("ClientCount", "i", property_get_client_count, 0, + SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_METHOD("RegisterGame", "i", "i", method_register_game, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("UnregisterGame", "i", "i", method_unregister_game, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("QueryStatus", "i", "i", method_query_status, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("RegisterGameByPID", "ii", "i", method_register_game_by_pid, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("UnregisterGameByPID", "ii", "i", method_unregister_game_by_pid, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("QueryStatusByPID", "ii", "i", method_query_status_by_pid, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_VTABLE_END +}; /** * Main process loop for the daemon. Run until quitting has been requested. diff --git a/daemon/dbus_messaging.h b/daemon/dbus_messaging.h index d02fb1c..6edbc0d 100644 --- a/daemon/dbus_messaging.h +++ b/daemon/dbus_messaging.h @@ -44,3 +44,8 @@ void game_mode_context_loop(GameModeContext *context) __attribute__((noreturn)); * Inhibit the screensaver */ int game_mode_inhibit_screensaver(bool inhibit); + +/** + * Signal the ClientCount property has changed + */ +void game_mode_client_count_changed(void); diff --git a/daemon/gamemode.c b/daemon/gamemode.c index 3bb8be4..9855fe6 100644 --- a/daemon/gamemode.c +++ b/daemon/gamemode.c @@ -415,6 +415,8 @@ int game_mode_context_register(GameModeContext *self, pid_t client, pid_t reques /* Apply io priorities */ game_mode_apply_ioprio(self, client); + game_mode_client_count_changed(); + return 0; error_cleanup: @@ -498,6 +500,8 @@ int game_mode_context_unregister(GameModeContext *self, pid_t client, pid_t requ game_mode_context_leave(self); } + game_mode_client_count_changed(); + return 0; }