1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2016 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
LoadDBUSSyms(void)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_get_args);
60 SDL_DBUS_SYM(message_iter_init);
61 SDL_DBUS_SYM(message_iter_next);
62 SDL_DBUS_SYM(message_iter_get_basic);
63 SDL_DBUS_SYM(message_iter_get_arg_type);
64 SDL_DBUS_SYM(message_iter_recurse);
65 SDL_DBUS_SYM(message_unref);
66 SDL_DBUS_SYM(error_init);
67 SDL_DBUS_SYM(error_is_set);
68 SDL_DBUS_SYM(error_free);
69 SDL_DBUS_SYM(get_local_machine_id);
70 SDL_DBUS_SYM(free);
71 SDL_DBUS_SYM(shutdown);
72
73 #undef SDL_DBUS_SYM
74 #undef SDL_DBUS_SYM2
75
76 return 0;
77 }
78
79 static void
UnloadDBUSLibrary(void)80 UnloadDBUSLibrary(void)
81 {
82 if (dbus_handle != NULL) {
83 SDL_UnloadObject(dbus_handle);
84 dbus_handle = NULL;
85 }
86 }
87
88 static int
LoadDBUSLibrary(void)89 LoadDBUSLibrary(void)
90 {
91 int retval = 0;
92 if (dbus_handle == NULL) {
93 dbus_handle = SDL_LoadObject(dbus_library);
94 if (dbus_handle == NULL) {
95 retval = -1;
96 /* Don't call SDL_SetError(): SDL_LoadObject already did. */
97 } else {
98 retval = LoadDBUSSyms();
99 if (retval < 0) {
100 UnloadDBUSLibrary();
101 }
102 }
103 }
104
105 return retval;
106 }
107
108 void
SDL_DBus_Init(void)109 SDL_DBus_Init(void)
110 {
111 if (!dbus.session_conn && LoadDBUSLibrary() != -1) {
112 DBusError err;
113 dbus.error_init(&err);
114 dbus.session_conn = dbus.bus_get_private(DBUS_BUS_SESSION, &err);
115 if (dbus.error_is_set(&err)) {
116 dbus.error_free(&err);
117 if (dbus.session_conn) {
118 dbus.connection_unref(dbus.session_conn);
119 dbus.session_conn = NULL;
120 }
121 return; /* oh well */
122 }
123 dbus.connection_set_exit_on_disconnect(dbus.session_conn, 0);
124 }
125 }
126
127 void
SDL_DBus_Quit(void)128 SDL_DBus_Quit(void)
129 {
130 if (dbus.session_conn) {
131 dbus.connection_close(dbus.session_conn);
132 dbus.connection_unref(dbus.session_conn);
133 dbus.shutdown();
134 SDL_memset(&dbus, 0, sizeof(dbus));
135 }
136 UnloadDBUSLibrary();
137 }
138
139 SDL_DBusContext *
SDL_DBus_GetContext(void)140 SDL_DBus_GetContext(void)
141 {
142 if(!dbus_handle || !dbus.session_conn){
143 SDL_DBus_Init();
144 }
145
146 if(dbus_handle && dbus.session_conn){
147 return &dbus;
148 } else {
149 return NULL;
150 }
151 }
152
153 void
SDL_DBus_ScreensaverTickle(void)154 SDL_DBus_ScreensaverTickle(void)
155 {
156 DBusConnection *conn = dbus.session_conn;
157 if (conn != NULL) {
158 DBusMessage *msg = dbus.message_new_method_call("org.gnome.ScreenSaver",
159 "/org/gnome/ScreenSaver",
160 "org.gnome.ScreenSaver",
161 "SimulateUserActivity");
162 if (msg != NULL) {
163 if (dbus.connection_send(conn, msg, NULL)) {
164 dbus.connection_flush(conn);
165 }
166 dbus.message_unref(msg);
167 }
168 }
169 }
170
171 SDL_bool
SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)172 SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)
173 {
174 DBusConnection *conn = dbus.session_conn;
175
176 if (conn == NULL)
177 return SDL_FALSE;
178
179 if (inhibit &&
180 screensaver_cookie != 0)
181 return SDL_TRUE;
182 if (!inhibit &&
183 screensaver_cookie == 0)
184 return SDL_TRUE;
185
186 if (inhibit) {
187 const char *app = "My SDL application";
188 const char *reason = "Playing a game";
189
190 DBusMessage *msg = dbus.message_new_method_call("org.freedesktop.ScreenSaver",
191 "/org/freedesktop/ScreenSaver",
192 "org.freedesktop.ScreenSaver",
193 "Inhibit");
194 if (msg != NULL) {
195 dbus.message_append_args (msg,
196 DBUS_TYPE_STRING, &app,
197 DBUS_TYPE_STRING, &reason,
198 DBUS_TYPE_INVALID);
199 }
200
201 if (msg != NULL) {
202 DBusMessage *reply;
203
204 reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
205 if (reply) {
206 if (!dbus.message_get_args(reply, NULL,
207 DBUS_TYPE_UINT32, &screensaver_cookie,
208 DBUS_TYPE_INVALID))
209 screensaver_cookie = 0;
210 dbus.message_unref(reply);
211 }
212
213 dbus.message_unref(msg);
214 }
215
216 if (screensaver_cookie == 0) {
217 return SDL_FALSE;
218 }
219 return SDL_TRUE;
220 } else {
221 DBusMessage *msg = dbus.message_new_method_call("org.freedesktop.ScreenSaver",
222 "/org/freedesktop/ScreenSaver",
223 "org.freedesktop.ScreenSaver",
224 "UnInhibit");
225 dbus.message_append_args (msg,
226 DBUS_TYPE_UINT32, &screensaver_cookie,
227 DBUS_TYPE_INVALID);
228 if (msg != NULL) {
229 if (dbus.connection_send(conn, msg, NULL)) {
230 dbus.connection_flush(conn);
231 }
232 dbus.message_unref(msg);
233 }
234
235 screensaver_cookie = 0;
236 return SDL_TRUE;
237 }
238 }
239 #endif
240