Skip to content

Latest commit

 

History

History
359 lines (319 loc) · 12.1 KB

SDL_dbus.c

File metadata and controls

359 lines (319 loc) · 12.1 KB
 
1
2
/*
Simple DirectMedia Layer
Jan 5, 2019
Jan 5, 2019
3
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#include "SDL_dbus.h"
#if SDL_USE_LIBDBUS
/* we never link directly to libdbus. */
#include "SDL_loadso.h"
static const char *dbus_library = "libdbus-1.so.3";
static void *dbus_handle = NULL;
static unsigned int screensaver_cookie = 0;
Oct 14, 2016
Oct 14, 2016
30
static SDL_DBusContext dbus;
31
32
33
34
35
static int
LoadDBUSSyms(void)
{
#define SDL_DBUS_SYM2(x, y) \
Feb 12, 2018
Feb 12, 2018
36
if (!(dbus.x = SDL_LoadFunction(dbus_handle, #y))) return -1
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#define SDL_DBUS_SYM(x) \
SDL_DBUS_SYM2(x, dbus_##x)
SDL_DBUS_SYM(bus_get_private);
SDL_DBUS_SYM(bus_register);
SDL_DBUS_SYM(bus_add_match);
SDL_DBUS_SYM(connection_open_private);
SDL_DBUS_SYM(connection_set_exit_on_disconnect);
SDL_DBUS_SYM(connection_get_is_connected);
SDL_DBUS_SYM(connection_add_filter);
SDL_DBUS_SYM(connection_try_register_object_path);
SDL_DBUS_SYM(connection_send);
SDL_DBUS_SYM(connection_send_with_reply_and_block);
SDL_DBUS_SYM(connection_close);
SDL_DBUS_SYM(connection_unref);
SDL_DBUS_SYM(connection_flush);
SDL_DBUS_SYM(connection_read_write);
SDL_DBUS_SYM(connection_dispatch);
SDL_DBUS_SYM(message_is_signal);
SDL_DBUS_SYM(message_new_method_call);
SDL_DBUS_SYM(message_append_args);
May 28, 2017
May 28, 2017
59
SDL_DBUS_SYM(message_append_args_valist);
60
SDL_DBUS_SYM(message_get_args);
May 28, 2017
May 28, 2017
61
SDL_DBUS_SYM(message_get_args_valist);
62
63
64
65
66
67
68
69
70
71
72
SDL_DBUS_SYM(message_iter_init);
SDL_DBUS_SYM(message_iter_next);
SDL_DBUS_SYM(message_iter_get_basic);
SDL_DBUS_SYM(message_iter_get_arg_type);
SDL_DBUS_SYM(message_iter_recurse);
SDL_DBUS_SYM(message_unref);
SDL_DBUS_SYM(error_init);
SDL_DBUS_SYM(error_is_set);
SDL_DBUS_SYM(error_free);
SDL_DBUS_SYM(get_local_machine_id);
SDL_DBUS_SYM(free);
May 28, 2017
May 28, 2017
73
SDL_DBUS_SYM(free_string_array);
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
SDL_DBUS_SYM(shutdown);
#undef SDL_DBUS_SYM
#undef SDL_DBUS_SYM2
return 0;
}
static void
UnloadDBUSLibrary(void)
{
if (dbus_handle != NULL) {
SDL_UnloadObject(dbus_handle);
dbus_handle = NULL;
}
}
static int
LoadDBUSLibrary(void)
{
int retval = 0;
if (dbus_handle == NULL) {
dbus_handle = SDL_LoadObject(dbus_library);
if (dbus_handle == NULL) {
retval = -1;
/* Don't call SDL_SetError(): SDL_LoadObject already did. */
} else {
retval = LoadDBUSSyms();
if (retval < 0) {
UnloadDBUSLibrary();
}
}
}
return retval;
}
void
SDL_DBus_Init(void)
{
Oct 9, 2019
Oct 9, 2019
114
115
116
117
118
119
static SDL_bool is_dbus_available = SDL_TRUE;
if (!is_dbus_available) {
return; /* don't keep trying if this fails. */
}
if (!dbus.session_conn) {
Oct 9, 2019
Oct 9, 2019
121
122
123
124
125
126
if (LoadDBUSLibrary() == -1) {
is_dbus_available = SDL_FALSE; /* can't load at all? Don't keep trying. */
return; /* oh well */
}
127
128
dbus.error_init(&err);
dbus.session_conn = dbus.bus_get_private(DBUS_BUS_SESSION, &err);
May 28, 2017
May 28, 2017
129
130
131
if (!dbus.error_is_set(&err)) {
dbus.system_conn = dbus.bus_get_private(DBUS_BUS_SYSTEM, &err);
}
132
133
if (dbus.error_is_set(&err)) {
dbus.error_free(&err);
May 28, 2017
May 28, 2017
134
SDL_DBus_Quit();
Oct 9, 2019
Oct 9, 2019
135
is_dbus_available = SDL_FALSE;
136
137
return; /* oh well */
}
May 28, 2017
May 28, 2017
138
dbus.connection_set_exit_on_disconnect(dbus.system_conn, 0);
139
140
141
142
143
144
145
dbus.connection_set_exit_on_disconnect(dbus.session_conn, 0);
}
}
void
SDL_DBus_Quit(void)
{
May 28, 2017
May 28, 2017
146
147
148
149
if (dbus.system_conn) {
dbus.connection_close(dbus.system_conn);
dbus.connection_unref(dbus.system_conn);
}
150
151
152
if (dbus.session_conn) {
dbus.connection_close(dbus.session_conn);
dbus.connection_unref(dbus.session_conn);
May 28, 2017
May 28, 2017
153
}
Feb 13, 2018
Feb 13, 2018
154
155
156
157
/* Don't do this - bug 3950
dbus_shutdown() is a debug feature which closes all global resources in the dbus library. Calling this should be done by the app, not a library, because if there are multiple users of dbus in the process then SDL could shut it down even though another part is using it.
*/
#if 0
May 28, 2017
May 28, 2017
158
if (dbus.shutdown) {
159
160
dbus.shutdown();
}
Feb 13, 2018
Feb 13, 2018
161
#endif
May 28, 2017
May 28, 2017
162
SDL_zero(dbus);
163
164
165
166
167
168
UnloadDBUSLibrary();
}
SDL_DBusContext *
SDL_DBus_GetContext(void)
{
Oct 9, 2019
Oct 9, 2019
169
if (!dbus_handle || !dbus.session_conn) {
170
171
172
SDL_DBus_Init();
}
Oct 9, 2019
Oct 9, 2019
173
return (dbus_handle && dbus.session_conn) ? &dbus : NULL;
May 28, 2017
May 28, 2017
176
177
static SDL_bool
SDL_DBus_CallMethodInternal(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap)
May 28, 2017
May 28, 2017
179
180
181
182
183
SDL_bool retval = SDL_FALSE;
if (conn) {
DBusMessage *msg = dbus.message_new_method_call(node, path, interface, method);
if (msg) {
Jul 13, 2018
Jul 13, 2018
184
185
186
187
int firstarg;
va_list ap_reply;
va_copy(ap_reply, ap); /* copy the arg list so we don't compete with D-Bus for it */
firstarg = va_arg(ap, int);
May 28, 2017
May 28, 2017
188
189
190
if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_append_args_valist(msg, firstarg, ap)) {
DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
if (reply) {
Jul 13, 2018
Jul 13, 2018
191
192
193
194
195
196
197
198
199
200
/* skip any input args, get to output args. */
while ((firstarg = va_arg(ap_reply, int)) != DBUS_TYPE_INVALID) {
/* we assume D-Bus already validated all this. */
{ void *dumpptr = va_arg(ap_reply, void*); (void) dumpptr; }
if (firstarg == DBUS_TYPE_ARRAY) {
{ const int dumpint = va_arg(ap_reply, int); (void) dumpint; }
}
}
firstarg = va_arg(ap_reply, int);
if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_get_args_valist(reply, NULL, firstarg, ap_reply)) {
May 28, 2017
May 28, 2017
201
202
203
204
retval = SDL_TRUE;
}
dbus.message_unref(reply);
}
Jul 13, 2018
Jul 13, 2018
206
va_end(ap_reply);
207
208
209
dbus.message_unref(msg);
}
}
May 28, 2017
May 28, 2017
210
211
return retval;
May 28, 2017
May 28, 2017
215
SDL_DBus_CallMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...)
May 28, 2017
May 28, 2017
217
218
219
220
221
222
223
SDL_bool retval;
va_list ap;
va_start(ap, method);
retval = SDL_DBus_CallMethodInternal(conn, node, path, interface, method, ap);
va_end(ap);
return retval;
}
May 28, 2017
May 28, 2017
225
226
227
228
229
230
231
232
233
234
SDL_bool
SDL_DBus_CallMethod(const char *node, const char *path, const char *interface, const char *method, ...)
{
SDL_bool retval;
va_list ap;
va_start(ap, method);
retval = SDL_DBus_CallMethodInternal(dbus.session_conn, node, path, interface, method, ap);
va_end(ap);
return retval;
}
May 28, 2017
May 28, 2017
236
237
238
239
static SDL_bool
SDL_DBus_CallVoidMethodInternal(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap)
{
SDL_bool retval = SDL_FALSE;
May 28, 2017
May 28, 2017
241
242
243
244
245
246
247
248
249
250
251
252
if (conn) {
DBusMessage *msg = dbus.message_new_method_call(node, path, interface, method);
if (msg) {
int firstarg = va_arg(ap, int);
if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_append_args_valist(msg, firstarg, ap)) {
if (dbus.connection_send(conn, msg, NULL)) {
dbus.connection_flush(conn);
retval = SDL_TRUE;
}
}
dbus.message_unref(msg);
May 28, 2017
May 28, 2017
254
}
May 28, 2017
May 28, 2017
256
257
return retval;
}
May 28, 2017
May 28, 2017
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
SDL_bool
SDL_DBus_CallVoidMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...)
{
SDL_bool retval;
va_list ap;
va_start(ap, method);
retval = SDL_DBus_CallVoidMethodInternal(conn, node, path, interface, method, ap);
va_end(ap);
return retval;
}
SDL_bool
SDL_DBus_CallVoidMethod(const char *node, const char *path, const char *interface, const char *method, ...)
{
SDL_bool retval;
va_list ap;
va_start(ap, method);
retval = SDL_DBus_CallVoidMethodInternal(dbus.session_conn, node, path, interface, method, ap);
va_end(ap);
return retval;
}
SDL_bool
SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result)
{
SDL_bool retval = SDL_FALSE;
May 28, 2017
May 28, 2017
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
if (conn) {
DBusMessage *msg = dbus.message_new_method_call(node, path, "org.freedesktop.DBus.Properties", "Get");
if (msg) {
if (dbus.message_append_args(msg, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) {
DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
if (reply) {
DBusMessageIter iter, sub;
dbus.message_iter_init(reply, &iter);
if (dbus.message_iter_get_arg_type(&iter) == DBUS_TYPE_VARIANT) {
dbus.message_iter_recurse(&iter, &sub);
if (dbus.message_iter_get_arg_type(&sub) == expectedtype) {
dbus.message_iter_get_basic(&sub, result);
retval = SDL_TRUE;
}
}
dbus.message_unref(reply);
}
}
304
305
dbus.message_unref(msg);
}
May 28, 2017
May 28, 2017
306
}
May 28, 2017
May 28, 2017
308
309
310
311
312
313
314
315
316
317
318
319
320
return retval;
}
SDL_bool
SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result)
{
return SDL_DBus_QueryPropertyOnConnection(dbus.session_conn, node, path, interface, property, expectedtype, result);
}
void
SDL_DBus_ScreensaverTickle(void)
{
Jul 2, 2019
Jul 2, 2019
321
322
323
324
325
if (screensaver_cookie == 0) { /* no need to tickle if we're inhibiting. */
/* org.gnome.ScreenSaver is the legacy interface, but it'll either do nothing or just be a second harmless tickle on newer systems, so we leave it for now. */
SDL_DBus_CallVoidMethod("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
SDL_DBus_CallVoidMethod("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver", "org.freedesktop.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
}
May 28, 2017
May 28, 2017
326
327
328
329
330
331
}
SDL_bool
SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)
{
if ( (inhibit && (screensaver_cookie != 0)) || (!inhibit && (screensaver_cookie == 0)) ) {
332
333
return SDL_TRUE;
} else {
May 28, 2017
May 28, 2017
334
335
336
337
338
339
340
341
342
343
344
const char *node = "org.freedesktop.ScreenSaver";
const char *path = "/org/freedesktop/ScreenSaver";
const char *interface = "org.freedesktop.ScreenSaver";
if (inhibit) {
const char *app = "My SDL application";
const char *reason = "Playing a game";
if (!SDL_DBus_CallMethod(node, path, interface, "Inhibit",
DBUS_TYPE_STRING, &app, DBUS_TYPE_STRING, &reason, DBUS_TYPE_INVALID,
DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) {
return SDL_FALSE;
May 28, 2017
May 28, 2017
346
347
348
349
350
351
return (screensaver_cookie != 0) ? SDL_TRUE : SDL_FALSE;
} else {
if (!SDL_DBus_CallVoidMethod(node, path, interface, "UnInhibit", DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) {
return SDL_FALSE;
}
screensaver_cookie = 0;
May 28, 2017
May 28, 2017
354
355
return SDL_TRUE;
Nov 29, 2016
Nov 29, 2016
358
359
/* vi: set ts=4 sw=4 expandtab: */