• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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