src/core/linux/SDL_dbus.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 02 Jan 2016 10:10:34 -0800
changeset 9998 f67cf37e9cd4
parent 9699 8e0e18edb270
child 10536 a6fa3f38672c
permissions -rw-r--r--
Updated copyright to 2016
     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 = {0};
    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.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
   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 *
   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
   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
   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