Atlas - SDL_dbus.c
Home / ext / SDL2 / src / core / linux Lines: 1 | Size: 11654 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 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" 27static const char *dbus_library = "libdbus-1.so.3"; 28static void *dbus_handle = NULL; 29static unsigned int screensaver_cookie = 0; 30static SDL_DBusContext dbus; 31 32static int 33LoadDBUSSyms(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 82static void 83UnloadDBUSLibrary(void) 84{ 85 if (dbus_handle != NULL) { 86 SDL_UnloadObject(dbus_handle); 87 dbus_handle = NULL; 88 } 89} 90 91static int 92LoadDBUSLibrary(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 111void 112SDL_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 131void 132SDL_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/* Don't do this - bug 3950 143 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. 144*/ 145#if 0 146 if (dbus.shutdown) { 147 dbus.shutdown(); 148 } 149#endif 150 SDL_zero(dbus); 151 UnloadDBUSLibrary(); 152} 153 154SDL_DBusContext * 155SDL_DBus_GetContext(void) 156{ 157 if(!dbus_handle || !dbus.session_conn){ 158 SDL_DBus_Init(); 159 } 160 161 if(dbus_handle && dbus.session_conn){ 162 return &dbus; 163 } else { 164 return NULL; 165 } 166} 167 168static SDL_bool 169SDL_DBus_CallMethodInternal(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap) 170{ 171 SDL_bool retval = SDL_FALSE; 172 173 if (conn) { 174 DBusMessage *msg = dbus.message_new_method_call(node, path, interface, method); 175 if (msg) { 176 int firstarg; 177 va_list ap_reply; 178 va_copy(ap_reply, ap); /* copy the arg list so we don't compete with D-Bus for it */ 179 firstarg = va_arg(ap, int); 180 if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_append_args_valist(msg, firstarg, ap)) { 181 DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL); 182 if (reply) { 183 /* skip any input args, get to output args. */ 184 while ((firstarg = va_arg(ap_reply, int)) != DBUS_TYPE_INVALID) { 185 /* we assume D-Bus already validated all this. */ 186 { void *dumpptr = va_arg(ap_reply, void*); (void) dumpptr; } 187 if (firstarg == DBUS_TYPE_ARRAY) { 188 { const int dumpint = va_arg(ap_reply, int); (void) dumpint; } 189 } 190 } 191 firstarg = va_arg(ap_reply, int); 192 if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_get_args_valist(reply, NULL, firstarg, ap_reply)) { 193 retval = SDL_TRUE; 194 } 195 dbus.message_unref(reply); 196 } 197 } 198 va_end(ap_reply); 199 dbus.message_unref(msg); 200 } 201 } 202 203 return retval; 204} 205 206SDL_bool 207SDL_DBus_CallMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...) 208{ 209 SDL_bool retval; 210 va_list ap; 211 va_start(ap, method); 212 retval = SDL_DBus_CallMethodInternal(conn, node, path, interface, method, ap); 213 va_end(ap); 214 return retval; 215} 216 217SDL_bool 218SDL_DBus_CallMethod(const char *node, const char *path, const char *interface, const char *method, ...) 219{ 220 SDL_bool retval; 221 va_list ap; 222 va_start(ap, method); 223 retval = SDL_DBus_CallMethodInternal(dbus.session_conn, node, path, interface, method, ap); 224 va_end(ap); 225 return retval; 226} 227 228static SDL_bool 229SDL_DBus_CallVoidMethodInternal(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap) 230{ 231 SDL_bool retval = SDL_FALSE; 232 233 if (conn) { 234 DBusMessage *msg = dbus.message_new_method_call(node, path, interface, method); 235 if (msg) { 236 int firstarg = va_arg(ap, int); 237 if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_append_args_valist(msg, firstarg, ap)) { 238 if (dbus.connection_send(conn, msg, NULL)) { 239 dbus.connection_flush(conn); 240 retval = SDL_TRUE; 241 } 242 } 243 244 dbus.message_unref(msg); 245 } 246 } 247 248 return retval; 249} 250 251SDL_bool 252SDL_DBus_CallVoidMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...) 253{ 254 SDL_bool retval; 255 va_list ap; 256 va_start(ap, method); 257 retval = SDL_DBus_CallVoidMethodInternal(conn, node, path, interface, method, ap); 258 va_end(ap); 259 return retval; 260} 261 262SDL_bool 263SDL_DBus_CallVoidMethod(const char *node, const char *path, const char *interface, const char *method, ...) 264{ 265 SDL_bool retval; 266 va_list ap; 267 va_start(ap, method); 268 retval = SDL_DBus_CallVoidMethodInternal(dbus.session_conn, node, path, interface, method, ap); 269 va_end(ap); 270 return retval; 271} 272 273SDL_bool 274SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result) 275{ 276 SDL_bool retval = SDL_FALSE; 277 278 if (conn) { 279 DBusMessage *msg = dbus.message_new_method_call(node, path, "org.freedesktop.DBus.Properties", "Get"); 280 if (msg) { 281 if (dbus.message_append_args(msg, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) { 282 DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL); 283 if (reply) { 284 DBusMessageIter iter, sub; 285 dbus.message_iter_init(reply, &iter); 286 if (dbus.message_iter_get_arg_type(&iter) == DBUS_TYPE_VARIANT) { 287 dbus.message_iter_recurse(&iter, &sub); 288 if (dbus.message_iter_get_arg_type(&sub) == expectedtype) { 289 dbus.message_iter_get_basic(&sub, result); 290 retval = SDL_TRUE; 291 } 292 } 293 dbus.message_unref(reply); 294 } 295 } 296 dbus.message_unref(msg); 297 } 298 } 299 300 return retval; 301} 302 303SDL_bool 304SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result) 305{ 306 return SDL_DBus_QueryPropertyOnConnection(dbus.session_conn, node, path, interface, property, expectedtype, result); 307} 308 309 310void 311SDL_DBus_ScreensaverTickle(void) 312{ 313 SDL_DBus_CallVoidMethod("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID); 314} 315 316SDL_bool 317SDL_DBus_ScreensaverInhibit(SDL_bool inhibit) 318{ 319 if ( (inhibit && (screensaver_cookie != 0)) || (!inhibit && (screensaver_cookie == 0)) ) { 320 return SDL_TRUE; 321 } else { 322 const char *node = "org.freedesktop.ScreenSaver"; 323 const char *path = "/org/freedesktop/ScreenSaver"; 324 const char *interface = "org.freedesktop.ScreenSaver"; 325 326 if (inhibit) { 327 const char *app = "My SDL application"; 328 const char *reason = "Playing a game"; 329 if (!SDL_DBus_CallMethod(node, path, interface, "Inhibit", 330 DBUS_TYPE_STRING, &app, DBUS_TYPE_STRING, &reason, DBUS_TYPE_INVALID, 331 DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) { 332 return SDL_FALSE; 333 } 334 return (screensaver_cookie != 0) ? SDL_TRUE : SDL_FALSE; 335 } else { 336 if (!SDL_DBus_CallVoidMethod(node, path, interface, "UnInhibit", DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) { 337 return SDL_FALSE; 338 } 339 screensaver_cookie = 0; 340 } 341 } 342 343 return SDL_TRUE; 344} 345#endif 346 347/* vi: set ts=4 sw=4 expandtab: */ 348[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.