src/core/linux/SDL_dbus.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 28 May 2017 07:08:10 -0400
changeset 11041 5aebcca5ff18
parent 10737 3406a0f8b041
child 11042 303c875e47f0
permissions -rw-r--r--
linux: Make system D-Bus connection available (in addition to session).
     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_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
    80 UnloadDBUSLibrary(void)
    81 {
    82     if (dbus_handle != NULL) {
    83         SDL_UnloadObject(dbus_handle);
    84         dbus_handle = NULL;
    85     }
    86 }
    87 
    88 static int
    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
   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.system_conn = dbus.bus_get_private(DBUS_BUS_SYSTEM, &err);
   117         }
   118         if (dbus.error_is_set(&err)) {
   119             dbus.error_free(&err);
   120             SDL_DBus_Quit();
   121             return;  /* oh well */
   122         }
   123         dbus.connection_set_exit_on_disconnect(dbus.system_conn, 0);
   124         dbus.connection_set_exit_on_disconnect(dbus.session_conn, 0);
   125     }
   126 }
   127 
   128 void
   129 SDL_DBus_Quit(void)
   130 {
   131     if (dbus.system_conn) {
   132         dbus.connection_close(dbus.system_conn);
   133         dbus.connection_unref(dbus.system_conn);
   134     }
   135     if (dbus.session_conn) {
   136         dbus.connection_close(dbus.session_conn);
   137         dbus.connection_unref(dbus.session_conn);
   138     }
   139     if (dbus.shutdown) {
   140         dbus.shutdown();
   141     }
   142     SDL_zero(dbus);
   143     UnloadDBUSLibrary();
   144 }
   145 
   146 SDL_DBusContext *
   147 SDL_DBus_GetContext(void)
   148 {
   149     if(!dbus_handle || !dbus.session_conn){
   150         SDL_DBus_Init();
   151     }
   152     
   153     if(dbus_handle && dbus.session_conn){
   154         return &dbus;
   155     } else {
   156         return NULL;
   157     }
   158 }
   159 
   160 void
   161 SDL_DBus_ScreensaverTickle(void)
   162 {
   163     DBusConnection *conn = dbus.session_conn;
   164     if (conn != NULL) {
   165         DBusMessage *msg = dbus.message_new_method_call("org.gnome.ScreenSaver",
   166                                                         "/org/gnome/ScreenSaver",
   167                                                         "org.gnome.ScreenSaver",
   168                                                         "SimulateUserActivity");
   169         if (msg != NULL) {
   170             if (dbus.connection_send(conn, msg, NULL)) {
   171                 dbus.connection_flush(conn);
   172             }
   173             dbus.message_unref(msg);
   174         }
   175     }
   176 }
   177 
   178 SDL_bool
   179 SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)
   180 {
   181     DBusConnection *conn = dbus.session_conn;
   182 
   183     if (conn == NULL)
   184         return SDL_FALSE;
   185 
   186     if (inhibit &&
   187         screensaver_cookie != 0)
   188         return SDL_TRUE;
   189     if (!inhibit &&
   190         screensaver_cookie == 0)
   191         return SDL_TRUE;
   192 
   193     if (inhibit) {
   194         const char *app = "My SDL application";
   195         const char *reason = "Playing a game";
   196 
   197         DBusMessage *msg = dbus.message_new_method_call("org.freedesktop.ScreenSaver",
   198                                                          "/org/freedesktop/ScreenSaver",
   199                                                          "org.freedesktop.ScreenSaver",
   200                                                          "Inhibit");
   201         if (msg != NULL) {
   202             dbus.message_append_args (msg,
   203                                       DBUS_TYPE_STRING, &app,
   204                                       DBUS_TYPE_STRING, &reason,
   205                                       DBUS_TYPE_INVALID);
   206         }
   207 
   208         if (msg != NULL) {
   209             DBusMessage *reply;
   210 
   211             reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
   212             if (reply) {
   213                 if (!dbus.message_get_args(reply, NULL,
   214                                            DBUS_TYPE_UINT32, &screensaver_cookie,
   215                                            DBUS_TYPE_INVALID))
   216                     screensaver_cookie = 0;
   217                 dbus.message_unref(reply);
   218             }
   219 
   220             dbus.message_unref(msg);
   221         }
   222 
   223         if (screensaver_cookie == 0) {
   224             return SDL_FALSE;
   225         }
   226         return SDL_TRUE;
   227     } else {
   228         DBusMessage *msg = dbus.message_new_method_call("org.freedesktop.ScreenSaver",
   229                                                         "/org/freedesktop/ScreenSaver",
   230                                                         "org.freedesktop.ScreenSaver",
   231                                                         "UnInhibit");
   232         dbus.message_append_args (msg,
   233                                   DBUS_TYPE_UINT32, &screensaver_cookie,
   234                                   DBUS_TYPE_INVALID);
   235         if (msg != NULL) {
   236             if (dbus.connection_send(conn, msg, NULL)) {
   237                 dbus.connection_flush(conn);
   238             }
   239             dbus.message_unref(msg);
   240         }
   241 
   242         screensaver_cookie = 0;
   243         return SDL_TRUE;
   244     }
   245 }
   246 #endif
   247 
   248 /* vi: set ts=4 sw=4 expandtab: */