SDL  2.0
SDL_dbus.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 #include "SDL_dbus.h"
23 
24 #if SDL_USE_LIBDBUS
25 /* we never link directly to libdbus. */
26 #include "SDL_loadso.h"
27 static const char *dbus_library = "libdbus-1.so.3";
28 static void *dbus_handle = NULL;
29 static unsigned int screensaver_cookie = 0;
30 static SDL_DBusContext dbus;
31 
32 static int
33 LoadDBUSSyms(void)
34 {
35  #define SDL_DBUS_SYM2(x, y) \
36  if (!(dbus.x = SDL_LoadFunction(dbus_handle, #y))) return -1
37 
38  #define SDL_DBUS_SYM(x) \
39  SDL_DBUS_SYM2(x, dbus_##x)
40 
41  SDL_DBUS_SYM(bus_get_private);
42  SDL_DBUS_SYM(bus_register);
43  SDL_DBUS_SYM(bus_add_match);
44  SDL_DBUS_SYM(connection_open_private);
45  SDL_DBUS_SYM(connection_set_exit_on_disconnect);
46  SDL_DBUS_SYM(connection_get_is_connected);
47  SDL_DBUS_SYM(connection_add_filter);
48  SDL_DBUS_SYM(connection_try_register_object_path);
49  SDL_DBUS_SYM(connection_send);
50  SDL_DBUS_SYM(connection_send_with_reply_and_block);
51  SDL_DBUS_SYM(connection_close);
52  SDL_DBUS_SYM(connection_unref);
53  SDL_DBUS_SYM(connection_flush);
54  SDL_DBUS_SYM(connection_read_write);
55  SDL_DBUS_SYM(connection_dispatch);
56  SDL_DBUS_SYM(message_is_signal);
57  SDL_DBUS_SYM(message_new_method_call);
58  SDL_DBUS_SYM(message_append_args);
59  SDL_DBUS_SYM(message_append_args_valist);
60  SDL_DBUS_SYM(message_get_args);
61  SDL_DBUS_SYM(message_get_args_valist);
62  SDL_DBUS_SYM(message_iter_init);
63  SDL_DBUS_SYM(message_iter_next);
64  SDL_DBUS_SYM(message_iter_get_basic);
65  SDL_DBUS_SYM(message_iter_get_arg_type);
66  SDL_DBUS_SYM(message_iter_recurse);
67  SDL_DBUS_SYM(message_unref);
68  SDL_DBUS_SYM(error_init);
69  SDL_DBUS_SYM(error_is_set);
70  SDL_DBUS_SYM(error_free);
71  SDL_DBUS_SYM(get_local_machine_id);
72  SDL_DBUS_SYM(free);
73  SDL_DBUS_SYM(free_string_array);
74  SDL_DBUS_SYM(shutdown);
75 
76  #undef SDL_DBUS_SYM
77  #undef SDL_DBUS_SYM2
78 
79  return 0;
80 }
81 
82 static void
83 UnloadDBUSLibrary(void)
84 {
85  if (dbus_handle != NULL) {
86  SDL_UnloadObject(dbus_handle);
87  dbus_handle = NULL;
88  }
89 }
90 
91 static int
92 LoadDBUSLibrary(void)
93 {
94  int retval = 0;
95  if (dbus_handle == NULL) {
96  dbus_handle = SDL_LoadObject(dbus_library);
97  if (dbus_handle == NULL) {
98  retval = -1;
99  /* Don't call SDL_SetError(): SDL_LoadObject already did. */
100  } else {
101  retval = LoadDBUSSyms();
102  if (retval < 0) {
103  UnloadDBUSLibrary();
104  }
105  }
106  }
107 
108  return retval;
109 }
110 
111 void
112 SDL_DBus_Init(void)
113 {
114  if (!dbus.session_conn && LoadDBUSLibrary() != -1) {
115  DBusError err;
116  dbus.error_init(&err);
117  dbus.session_conn = dbus.bus_get_private(DBUS_BUS_SESSION, &err);
118  if (!dbus.error_is_set(&err)) {
119  dbus.system_conn = dbus.bus_get_private(DBUS_BUS_SYSTEM, &err);
120  }
121  if (dbus.error_is_set(&err)) {
122  dbus.error_free(&err);
123  SDL_DBus_Quit();
124  return; /* oh well */
125  }
126  dbus.connection_set_exit_on_disconnect(dbus.system_conn, 0);
127  dbus.connection_set_exit_on_disconnect(dbus.session_conn, 0);
128  }
129 }
130 
131 void
132 SDL_DBus_Quit(void)
133 {
134  if (dbus.system_conn) {
135  dbus.connection_close(dbus.system_conn);
136  dbus.connection_unref(dbus.system_conn);
137  }
138  if (dbus.session_conn) {
139  dbus.connection_close(dbus.session_conn);
140  dbus.connection_unref(dbus.session_conn);
141  }
142  if (dbus.shutdown) {
143  dbus.shutdown();
144  }
145  SDL_zero(dbus);
146  UnloadDBUSLibrary();
147 }
148 
149 SDL_DBusContext *
150 SDL_DBus_GetContext(void)
151 {
152  if(!dbus_handle || !dbus.session_conn){
153  SDL_DBus_Init();
154  }
155 
156  if(dbus_handle && dbus.session_conn){
157  return &dbus;
158  } else {
159  return NULL;
160  }
161 }
162 
163 static SDL_bool
164 SDL_DBus_CallMethodInternal(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap)
165 {
166  SDL_bool retval = SDL_FALSE;
167 
168  if (conn) {
169  DBusMessage *msg = dbus.message_new_method_call(node, path, interface, method);
170  if (msg) {
171  int firstarg = va_arg(ap, int);
172  if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_append_args_valist(msg, firstarg, ap)) {
173  DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
174  if (reply) {
175  firstarg = va_arg(ap, int);
176  if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_get_args_valist(reply, NULL, firstarg, ap)) {
177  retval = SDL_TRUE;
178  }
179  dbus.message_unref(reply);
180  }
181  }
182  dbus.message_unref(msg);
183  }
184  }
185 
186  return retval;
187 }
188 
189 SDL_bool
190 SDL_DBus_CallMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...)
191 {
193  va_list ap;
194  va_start(ap, method);
195  retval = SDL_DBus_CallMethodInternal(conn, node, path, interface, method, ap);
196  va_end(ap);
197  return retval;
198 }
199 
200 SDL_bool
201 SDL_DBus_CallMethod(const char *node, const char *path, const char *interface, const char *method, ...)
202 {
204  va_list ap;
205  va_start(ap, method);
206  retval = SDL_DBus_CallMethodInternal(dbus.session_conn, node, path, interface, method, ap);
207  va_end(ap);
208  return retval;
209 }
210 
211 static SDL_bool
212 SDL_DBus_CallVoidMethodInternal(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap)
213 {
214  SDL_bool retval = SDL_FALSE;
215 
216  if (conn) {
217  DBusMessage *msg = dbus.message_new_method_call(node, path, interface, method);
218  if (msg) {
219  int firstarg = va_arg(ap, int);
220  if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_append_args_valist(msg, firstarg, ap)) {
221  if (dbus.connection_send(conn, msg, NULL)) {
222  dbus.connection_flush(conn);
223  retval = SDL_TRUE;
224  }
225  }
226 
227  dbus.message_unref(msg);
228  }
229  }
230 
231  return retval;
232 }
233 
234 SDL_bool
235 SDL_DBus_CallVoidMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...)
236 {
238  va_list ap;
239  va_start(ap, method);
240  retval = SDL_DBus_CallVoidMethodInternal(conn, node, path, interface, method, ap);
241  va_end(ap);
242  return retval;
243 }
244 
245 SDL_bool
246 SDL_DBus_CallVoidMethod(const char *node, const char *path, const char *interface, const char *method, ...)
247 {
249  va_list ap;
250  va_start(ap, method);
251  retval = SDL_DBus_CallVoidMethodInternal(dbus.session_conn, node, path, interface, method, ap);
252  va_end(ap);
253  return retval;
254 }
255 
256 SDL_bool
257 SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result)
258 {
259  SDL_bool retval = SDL_FALSE;
260 
261  if (conn) {
262  DBusMessage *msg = dbus.message_new_method_call(node, path, "org.freedesktop.DBus.Properties", "Get");
263  if (msg) {
264  if (dbus.message_append_args(msg, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) {
265  DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
266  if (reply) {
267  DBusMessageIter iter, sub;
268  dbus.message_iter_init(reply, &iter);
269  if (dbus.message_iter_get_arg_type(&iter) == DBUS_TYPE_VARIANT) {
270  dbus.message_iter_recurse(&iter, &sub);
271  if (dbus.message_iter_get_arg_type(&sub) == expectedtype) {
272  dbus.message_iter_get_basic(&sub, result);
273  retval = SDL_TRUE;
274  }
275  }
276  dbus.message_unref(reply);
277  }
278  }
279  dbus.message_unref(msg);
280  }
281  }
282 
283  return retval;
284 }
285 
286 SDL_bool
287 SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result)
288 {
289  return SDL_DBus_QueryPropertyOnConnection(dbus.session_conn, node, path, interface, property, expectedtype, result);
290 }
291 
292 
293 void
294 SDL_DBus_ScreensaverTickle(void)
295 {
296  SDL_DBus_CallVoidMethod("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
297 }
298 
299 SDL_bool
300 SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)
301 {
302  if ( (inhibit && (screensaver_cookie != 0)) || (!inhibit && (screensaver_cookie == 0)) ) {
303  return SDL_TRUE;
304  } else {
305  const char *node = "org.freedesktop.ScreenSaver";
306  const char *path = "/org/freedesktop/ScreenSaver";
307  const char *interface = "org.freedesktop.ScreenSaver";
308 
309  if (inhibit) {
310  const char *app = "My SDL application";
311  const char *reason = "Playing a game";
312  if (!SDL_DBus_CallMethod(node, path, interface, "Inhibit",
313  DBUS_TYPE_STRING, &app, DBUS_TYPE_STRING, &reason, DBUS_TYPE_INVALID,
314  DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) {
315  return SDL_FALSE;
316  }
317  return (screensaver_cookie != 0) ? SDL_TRUE : SDL_FALSE;
318  } else {
319  if (!SDL_DBus_CallVoidMethod(node, path, interface, "UnInhibit", DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) {
320  return SDL_FALSE;
321  }
322  screensaver_cookie = 0;
323  }
324  }
325 
326  return SDL_TRUE;
327 }
328 #endif
329 
330 /* vi: set ts=4 sw=4 expandtab: */
GLuint64EXT * result
SDL_EventEntry * free
Definition: SDL_events.c:83
#define SDL_LoadObject
#define SDL_UnloadObject
SDL_bool retval
#define SDL_zero(x)
Definition: SDL_stdinc.h:369
#define NULL
Definition: begin_code.h:164
SDL_bool
Definition: SDL_stdinc.h:139
GLsizei const GLchar *const * path