/** * Same example as client-stubs, but implementing the asynchronous * logic by using GLib/D-Bus wrapper functions directly. This version * of the asynchronous client does not require the generated stubs. * * This maemo code example is licensed under a MIT-style license, * that can be found in the file called "License" in the same * directory as this file. * Copyright (c) 2007-2008 Nokia Corporation. All rights reserved. */ #include #include #include /* exit */ /* Pull the common symbolic defines. */ #include "common-defs.h" /** * Print out an error message and optionally quit (if fatal is TRUE) */ static void handleError(const char* msg, const char* reason, gboolean fatal) { g_printerr(PROGNAME ": ERROR: %s (%s)\n", msg, reason); if (fatal) { exit(EXIT_FAILURE); } } /** * This function will be called when the async setvalue1 will either * complete, timeout or fail (same as before). The main difference in * using GLib/D-Bus wrappers is that we need to "collect" the return * value (or error). This is done with the _end_call function. * * Note that all callbacks that are to be registered for RPC async * notifications using dbus_g_proxy_begin_call must follow the * following prototype: DBusGProxyCallNotify . */ static void setValue1Completed(DBusGProxy* proxy, DBusGProxyCall* call, gpointer userData) { /* This will hold the GError object (if any). */ GError* error = NULL; g_print(PROGNAME ":setValue1Completed\n"); /* We next need to collect the results from the RPC call. The function returns FALSE on errors (which we check), although we could also check whether error-ptr is still NULL. */ if (!dbus_g_proxy_end_call(proxy, /* The call that we are collecting. */ call, /* Where to store the error (if any). */ &error, /* Next we list the GType codes for all the arguments we expect back. In our case there are none, so set to invalid. */ G_TYPE_INVALID)) { /* Some error occurred while collecting the result. */ g_printerr(PROGNAME " ERROR: %s\n", error->message); g_error_free(error); } else { g_print(PROGNAME " SUCCESS\n"); } } /** * This function will be called repeatedly from within the mainloop * timer launch code. * * It will launch asynchronous RPC method to set value1 with ever * increasing argument. */ static gboolean timerCallback(DBusGProxy* remoteobj) { /* Local value that we will start updating to the remote object. */ static gint localValue1 = -80; /* Start the first RPC. The call using GLib/D-Bus is only slightly more complex than the stubs. The overall operation is the same. */ g_print(PROGNAME ":timerCallback launching setvalue1\n"); dbus_g_proxy_begin_call(remoteobj, /* Method name. */ "setvalue1", /* Callback to call on "completion". */ setValue1Completed, /* User-data to pass to callback. */ NULL, /* Function to call to free userData after callback returns. */ NULL, /* First argument GType. */ G_TYPE_INT, /* First argument value (passed by value) */ localValue1, /* Terminate argument list. */ G_TYPE_INVALID); g_print(PROGNAME ":timerCallback setvalue1 launched\n"); /* Step the local value forward. */ localValue1 += 10; /* Repeat timer later. */ return TRUE; } /** * The test program itself. * * 1) Setup GType/GSignal * 2) Create GMainLoop object * 3) Connect to the Session D-Bus * 4) Create a proxy GObject for the remote Value object * 5) Start a timer that will launch timerCallback once per second. * 6) Run main-loop (forever) */ int main(int argc, char** argv) { DBusGConnection* bus; /* The proxy object. */ DBusGProxy* remoteValue; GMainLoop* mainloop; GError* error = NULL; g_type_init(); mainloop = g_main_loop_new(NULL, FALSE); /* Failure to create the main loop is fatal (for us). */ if (mainloop == NULL) { handleError("Failed to create the mainloop", "Unknown (OOM?)", TRUE); } g_print(PROGNAME ":main Connecting to Session D-Bus.\n"); bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error); if (error != NULL) { handleError("Could not connect to the Session bus", error->message, TRUE); } g_print(PROGNAME ":main Creating a GLib proxy object for Value.\n"); remoteValue = dbus_g_proxy_new_for_name(bus, VALUE_SERVICE_NAME, /* name */ VALUE_SERVICE_OBJECT_PATH, /* obj path */ VALUE_SERVICE_INTERFACE /* interface */); if (remoteValue == NULL) { handleError("Could not create the proxy object", "Unknown(dbus_g_proxy_new_for_name)", TRUE); } g_print(PROGNAME ":main Starting main loop (first timer in 1s).\n"); g_timeout_add(1000, (GSourceFunc)timerCallback, remoteValue); /* Run the program. */ g_main_loop_run(mainloop); /* Since the main loop is not stopped (by this code), we should not ever get here. The program might abort() for other reasons. */ /* If it does, return failure as exit code. */ return 1; }