mirror of
https://github.com/FeralInteractive/gamemode.git
synced 2025-08-06 05:08:29 +02:00
Add gamemode_query_status and teach gamemoded '-s'
This allows the client to query the daemon about the status of gamemode. Returns the following: 0 if gamemode is inactive 1 if gamemode is active 2 if gamemode is active and this client is registered -1 if the query failed Passing -s to gamemoded will simply query and print the current status. Allows for more comprehensive testing when using 'gamemoded -r' as well as more reactionary program behaviour
This commit is contained in:
@@ -101,6 +101,26 @@ static int method_unregister_game(sd_bus_message *m, void *userdata,
|
||||
return sd_bus_reply_method_return(m, "i", 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the QueryStatus D-BUS Method
|
||||
*/
|
||||
static int method_query_status(sd_bus_message *m, void *userdata,
|
||||
__attribute__((unused)) sd_bus_error *ret_error)
|
||||
{
|
||||
int pid = 0;
|
||||
GameModeContext *context = userdata;
|
||||
|
||||
int ret = sd_bus_message_read(m, "i", &pid);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR("Failed to parse input parameters: %s\n", strerror(-ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int status = game_mode_context_query_status(context, (pid_t)pid);
|
||||
|
||||
return sd_bus_reply_method_return(m, "i", status);
|
||||
}
|
||||
|
||||
/**
|
||||
* D-BUS vtable to dispatch virtual methods
|
||||
*/
|
||||
@@ -108,6 +128,7 @@ 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_VTABLE_END };
|
||||
|
||||
/**
|
||||
|
@@ -366,6 +366,40 @@ bool game_mode_context_unregister(GameModeContext *self, pid_t client)
|
||||
return true;
|
||||
}
|
||||
|
||||
int game_mode_context_query_status(GameModeContext *self, pid_t client)
|
||||
{
|
||||
GameModeClient *cl = NULL;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* Check the current refcount on gamemode, this equates to whether gamemode is active or not,
|
||||
* see game_mode_context_register and game_mode_context_unregister
|
||||
*/
|
||||
if (atomic_load_explicit(&self->refcount, memory_order_seq_cst)) {
|
||||
ret++;
|
||||
|
||||
/* Check if the current client is registered */
|
||||
|
||||
/* Requires locking. */
|
||||
pthread_rwlock_rdlock(&self->rwlock);
|
||||
|
||||
for (cl = self->client; cl; cl = cl->next) {
|
||||
if (cl->pid != client) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Found it */
|
||||
ret++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Unlock here, potentially yielding */
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new GameModeClient for the given process ID
|
||||
*
|
||||
|
@@ -73,3 +73,13 @@ bool game_mode_context_register(GameModeContext *self, pid_t pid);
|
||||
* @returns True if the client was removed, and existed.
|
||||
*/
|
||||
bool game_mode_context_unregister(GameModeContext *self, pid_t pid);
|
||||
|
||||
/**
|
||||
* Query the current status of gamemode
|
||||
*
|
||||
* @param pid Process ID for the remote client
|
||||
* @returns Positive if gamemode is active
|
||||
* 1 if gamemode is active but the client is not registered
|
||||
* 2 if gamemode is active and the client is registered
|
||||
*/
|
||||
int game_mode_context_query_status(GameModeContext *self, pid_t pid);
|
||||
|
@@ -96,7 +96,7 @@ int main(int argc, char *argv[])
|
||||
bool daemon = false;
|
||||
bool use_syslog = false;
|
||||
int opt = 0;
|
||||
while ((opt = getopt(argc, argv, "dlrvh")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "dlsrvh")) != -1) {
|
||||
switch (opt) {
|
||||
case 'd':
|
||||
daemon = true;
|
||||
@@ -104,13 +104,38 @@ int main(int argc, char *argv[])
|
||||
case 'l':
|
||||
use_syslog = true;
|
||||
break;
|
||||
case 's': {
|
||||
int status;
|
||||
|
||||
if ((status = gamemode_query_status()) < 0) {
|
||||
fprintf(stderr, "gamemode status request failed: %s\n", gamemode_error_string());
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (status > 0) {
|
||||
fprintf(stdout, "gamemode is active\n");
|
||||
} else {
|
||||
fprintf(stdout, "gamemode is inactive\n");
|
||||
}
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
}
|
||||
case 'r':
|
||||
if (gamemode_request_start() < 0) {
|
||||
fprintf(stderr, "gamemode request failed: %s\n", gamemode_error_string());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fprintf(stdout, "gamemode request succeeded...\n");
|
||||
int status = gamemode_query_status();
|
||||
if (status == 2) {
|
||||
fprintf(stdout, "gamemode request succeeded and is active\n");
|
||||
} else if (status == 1) {
|
||||
fprintf(stderr,
|
||||
"gamemode request succeeded and is active but registration failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
fprintf(stderr, "gamemode request succeeded but is not active\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Simply pause and wait for any signal
|
||||
pause();
|
||||
|
Reference in New Issue
Block a user