B. Source code for the LibOSSO RPC examples
- B.1 libosso-example-sync/libosso-rpc-sync.c
- B.2 libosso-example-sync/Makefile
- B.3 libosso-example-async/libosso-rpc-async.c
- B.4 libosso-example-async/Makefile
B. Source code for the LibOSSO RPC examples
B.1 libosso-example-sync/libosso-rpc-sync.c
libosso-example-sync/libosso-rpc-sync.c/** * A program that will issue a "system_note_dialog" RPC method call. * * 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. * * In function does the same as dbus-example.c, but this time * utilizing LibOSSO _rpc-functions (synchronously). * * It would be unfair to compare this program directly against the * dbus-example.c, since this program contains additional * functionality. In general using the LibOSSO _rpc functions will * lead to more compact code, but there are cases when you need to go * beyond what LibOSSO provides (and using the GLib/D-Bus interface is * the proper way to go in that case). * * Please run with run-standalone.sh (LibOSSO initialization will fail * otherwise). */ #include <glib.h> #include <libosso.h> #include <stdlib.h> /* EXIT_SUCCESS */ /* Symbolic defines for the D-Bus well-known name, interface, object path and method name that we're going to use. Same as before. These are defined in osso-internal.h but we cannot use it here. */ #define SYSNOTE_NAME "org.freedesktop.Notifications" #define SYSNOTE_OPATH "/org/freedesktop/Notifications" #define SYSNOTE_IFACE "org.freedesktop.Notifications" #define SYSNOTE_NOTE "SystemNoteDialog" /** * Utility to return a pointer to a statically allocated string giving * the textural representation of LibOSSO errors. Has no internal * state (safe to use from threads). * * LibOSSO does not come with a function for this, so we define one * ourselves. */ static const gchar* ossoErrorStr(osso_return_t errCode) { switch (errCode) { case OSSO_OK: return "No error (OSSO_OK)"; case OSSO_ERROR: return "Some kind of error occurred (OSSO_ERROR)"; case OSSO_INVALID: return "At least one parameter is invalid (OSSO_INVALID)"; case OSSO_RPC_ERROR: return "Osso RPC method returned an error (OSSO_RPC_ERROR)"; case OSSO_ERROR_NAME: return "(undocumented error) (OSSO_ERROR_NAME)"; case OSSO_ERROR_NO_STATE: return "No state file found to read (OSSO_ERROR_NO_STATE)"; case OSSO_ERROR_STATE_SIZE: return "Size of state file unexpected (OSSO_ERROR_STATE_SIZE)"; default: return "Unknown/Undefined"; } } /** * Utility to print out the type and content of given osso_rpc_t. * It also demonstrates the types available when using LibOSSO for * the RPC. Most simple types are available, but arrays are not * (unfortunately). */ static void printOssoValue(const osso_rpc_t* val) { g_assert(val != NULL); switch (val->type) { case DBUS_TYPE_BOOLEAN: g_print("boolean:%s", (val->value.b == TRUE)?"TRUE":"FALSE"); break; case DBUS_TYPE_DOUBLE: g_print("double:%.3f", val->value.d); break; case DBUS_TYPE_INT32: g_print("int32:%d", val->value.i); break; case DBUS_TYPE_UINT32: g_print("uint32:%u", val->value.u); break; case DBUS_TYPE_STRING: g_print("string:'%s'", val->value.s); break; case DBUS_TYPE_INVALID: g_print("invalid/void"); break; default: g_print("unknown(type=%d)", val->type); break; } } /** * Do the RPC call. * * Note that this function will block until the method call either * succeeds, or fails. If the method call would take a long time to * run, this would block the GUI of the program (which we don't have). * * Needs the LibOSSO state to do the launch. */ static void runRPC(osso_context_t* ctx) { /* Message to display. */ const char* dispMsg = "Hello SystemNote!\nVia LibOSSO/sync."; /* Icon type to use. */ gint iconType = OSSO_GN_ERROR; /* Button label text to use, "" means leaving the defaults. */ const char* labelText = ""; /* Will hold the result from the RPC invocation function. */ osso_return_t result; /* Will hold the result of the method call (or error). */ osso_rpc_t methodResult = {}; g_print("runRPC called\n"); g_assert(ctx != NULL); /* Compared to the libdbus functions, LibOSSO provides conveniently a function that will do the dispatch and also allows us to pass the arguments all with one call. The arguments for the "SystemNoteDialog" are the same as in dbus-example.c (since it is the same service). You might also notice that even if LibOSSO provides some convenience, it does not completely isolate us from libdbus. We still supply the argument types using D-Bus constants. NOTE Do not pass the argument values by pointers as with libdbus, instead pass them by value (as below). */ result = osso_rpc_run(ctx, SYSNOTE_NAME, /* well-known name */ SYSNOTE_OPATH, /* object path */ SYSNOTE_IFACE, /* interface */ SYSNOTE_NOTE, /* method name */ &methodResult, /* method return value */ /* The arguments for the RPC. The types are unchanged, but instead of passing them via pointers, they're passed by "value" instead. */ DBUS_TYPE_STRING, dispMsg, DBUS_TYPE_UINT32, iconType, DBUS_TYPE_STRING, labelText, DBUS_TYPE_INVALID); /* Check whether launching the RPC succeeded. */ if (result != OSSO_OK) { g_error("Error launching the RPC (%s)\n", ossoErrorStr(result)); /* We also terminate right away since there's nothing to do. */ } g_print("RPC launched successfully\n"); /* Now decode the return data from the method call. NOTE: If there is an error during RPC delivery, the return value will be a string. It is not possible to differentiate that condition from an RPC call that returns a string. If a method returns "void", the type-field in the methodResult will be set to DBUS_TYPE_INVALID. This is not an error. */ g_print("Method returns: "); printOssoValue(&methodResult); g_print("\n"); g_print("runRPC ending\n"); } int main(int argc, char** argv) { /* The LibOSSO context that we need to do RPC. */ osso_context_t* ossoContext = NULL; g_print("Initializing LibOSSO\n"); /* The program name for registration is communicated from the Makefile via a -D preprocessor directive. Since it doesn't contain any dots in it, a prefix of "com.nokia." will be added to it internally within osso_initialize(). */ ossoContext = osso_initialize(ProgName, "1.0", FALSE, NULL); if (ossoContext == NULL) { g_error("Failed to initialize LibOSSO\n"); } g_print("Invoking the method call\n"); runRPC(ossoContext); g_print("Shutting down LibOSSO\n"); /* Deinitialize LibOSSO. The function doesn't return status code so we cannot know whether it succeeded or failed. We assume that it always succeeds. */ osso_deinitialize(ossoContext); ossoContext = NULL; g_print("Quitting\n"); return EXIT_SUCCESS; }
B.2 libosso-example-sync/Makefile
libosso-example-sync/Makefile# # Simple Makefile to build the LibOSSO/Async-RPC example # # define a list of pkg-config packages we want to use pkg_packages := glib-2.0 libosso PKG_CFLAGS := $(shell pkg-config -cflags $(pkg_packages)) PKG_LDFLAGS := $(shell pkg-config -libs $(pkg_packages)) # add warnings and debugging info CFLAGS-variable ADD_CFLAGS += -g -Wall # Combine user supplied, additional and pkg-config flags CFLAGS := $(PKG_CFLAGS) $(ADD_CFLAGS) $(CFLAGS) LDFLAGS := $(PKG_LDFLAGS) $(LDFLAGS) targets = libosso-rpc-sync all: $(targets) libosso-rpc-sync: libosso-rpc-sync.c $(CC) $(CFLAGS) -DProgName=\"LibOSSOExample\" \ $< -o $@ $(LDFLAGS) .PHONY: clean all clean: $(RM) $(targets)
B.3 libosso-example-async/libosso-rpc-async.c
libosso-example-async/libosso-rpc-async.c/** * A program that will issue a "system_note_dialog" RPC method call. * * 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. * * In function does the same as dbus-example.c, but this time * utilizing LibOSSO _rpc-functions and demonstrating how to integrate * asynchronous calls with LibOSSO. * * It would be unfair to compare this program directly against the * dbus-example.c, since this program contains additional * functionality. In general using the LibOSSO _rpc functions will * lead to more compact code, but there are cases when you need to go * beyond what LibOSSO provides (and using the GLib/D-Bus interface is * the proper way to go in that case). * * Please run with run-standalone.sh (LibOSSO initialization will fail * otherwise). */ #include <glib.h> #include <libosso.h> #include <stdlib.h> /* EXIT_SUCCESS */ /* Symbolic defines for the D-Bus well-known name, interface, object path and method name that we're going to use. Same as before. These are defined in osso-internal.h but we cannot use it here. */ #define SYSNOTE_NAME "org.freedesktop.Notifications" #define SYSNOTE_OPATH "/org/freedesktop/Notifications" #define SYSNOTE_IFACE "org.freedesktop.Notifications" #define SYSNOTE_NOTE "SystemNoteDialog" /** * Small application state so that we can pass both LibOSSO context * and the mainloop around to the callbacks. */ typedef struct { /* A mainloop object that will "drive" our example. */ GMainLoop* mainloop; /* The LibOSSO context which we use to do RPC. */ osso_context_t* ossoContext; } ApplicationState; /** * Utility to return a pointer to a statically allocated string giving * the textural representation of LibOSSO errors. Has no internal * state (safe to use from threads). * * LibOSSO does not come with a function for this, so we define one * ourselves. */ static const gchar* ossoErrorStr(osso_return_t errCode) { switch (errCode) { case OSSO_OK: return "No error (OSSO_OK)"; case OSSO_ERROR: return "Some kind of error occurred (OSSO_ERROR)"; case OSSO_INVALID: return "At least one parameter is invalid (OSSO_INVALID)"; case OSSO_RPC_ERROR: return "Osso RPC method returned an error (OSSO_RPC_ERROR)"; case OSSO_ERROR_NAME: return "(undocumented error) (OSSO_ERROR_NAME)"; case OSSO_ERROR_NO_STATE: return "No state file found to read (OSSO_ERROR_NO_STATE)"; case OSSO_ERROR_STATE_SIZE: return "Size of state file unexpected (OSSO_ERROR_STATE_SIZE)"; default: return "Unknown/Undefined"; } } /** * Utility to print out the type and content of given osso_rpc_t. * It also demonstrates the types available when using LibOSSO for * the RPC. Most simple types are available, but arrays are not * (unfortunately). */ static void printOssoValue(const osso_rpc_t* val) { g_assert(val != NULL); switch (val->type) { case DBUS_TYPE_BOOLEAN: g_print("boolean:%s", (val->value.b == TRUE)?"TRUE":"FALSE"); break; case DBUS_TYPE_DOUBLE: g_print("double:%.3f", val->value.d); break; case DBUS_TYPE_INT32: g_print("int32:%d", val->value.i); break; case DBUS_TYPE_UINT32: g_print("uint32:%u", val->value.u); break; case DBUS_TYPE_STRING: g_print("string:'%s'", val->value.s); break; case DBUS_TYPE_INVALID: g_print("invalid/void"); break; default: g_print("unknown(type=%d)", val->type); break; } } /** * Will be called from LibOSSO when the RPC return data is available. * Will print out the result, and return. Note that it must not free * the value, since it does not own it. * * The prototype (for reference) must be osso_rpc_async_f(). * * The parameters for the callback are the D-Bus interface and method * names (note that object path and well-known name are NOT * communicated). The idea is that you can then reuse the same * callback to process completions from multiple simple RPC calls. */ static void rpcCompletedCallback(const gchar* interface, const gchar* method, osso_rpc_t* retVal, gpointer userData) { ApplicationState* state = (ApplicationState*)userData; g_print("rpcCompletedCallback called\n"); g_assert(interface != NULL); g_assert(method != NULL); g_assert(retVal != NULL); g_assert(state != NULL); g_print(" interface: %s\n", interface); g_print(" method: %s\n", method); /* NOTE If there is an error in the RPC delivery, the return value will be a string. This is unfortunate if your RPC call is supposed to return a string as well, since it is not possible to differentiate between the two cases. If a method returns "void", the type-field in the retVal will be set to DBUS_TYPE_INVALID (it's not an error). */ g_print(" result: "); printOssoValue(retVal); g_print("\n"); /* Tell the main loop to terminate. */ g_main_loop_quit(state->mainloop); g_print("rpcCompletedCallback done\n"); } /** * We launch the RPC call from within a timer callback in order to * make sure that a mainloop object will be running when the RPC will * return (to avoid a nasty race condition). * * So, in essence this is a one-shot timer callback. * * In order to launch the RPC, it will need to get a valid LibOSSO * context (which is carried via the userData/application state * parameter). */ static gboolean launchRPC(gpointer userData) { ApplicationState* state = (ApplicationState*)userData; /* Message to display. */ const char* dispMsg = "Hello SystemNote!\nVia LibOSSO/async."; /* Icon type to use. */ gint iconType = OSSO_GN_ERROR; /* Button label text to use. */ const char* labelText = "Execute!"; /* Will hold the result from the RPC launch call. */ osso_return_t result; g_print("launchRPC called\n"); g_assert(state != NULL); /* Compared to the libdbus functions, LibOSSO provides conveniently a function that will do the dispatch, registration of callbacks and allow argument supplying in one call. The arguments for the "system_note_dialog" are the same as in dbus-example.c (since it is the same service). You might also notice that even if LibOSSO provides some convenience, it does not completely isolate us from libdbus. We still supply the argument types using D-Bus constants. NOTE Do not pass the argument values by pointers as with libdbus, instead pass them by value (as below). */ /* The only difference compared to the synchronous version is the addition of the callback function parameter, and the user-data parameter for data that will be passed to the callback. */ result = osso_rpc_async_run(state->ossoContext, SYSNOTE_NAME, /* well-known name */ SYSNOTE_OPATH, /* object path */ SYSNOTE_IFACE, /* interface */ SYSNOTE_NOTE, /* method name */ rpcCompletedCallback, /* async cb */ state, /* user-data for cb */ /* The arguments for the RPC. */ DBUS_TYPE_STRING, dispMsg, DBUS_TYPE_UINT32, iconType, DBUS_TYPE_STRING, labelText, DBUS_TYPE_INVALID); /* Check whether launching the RPC succeeded (we don't know the result from the RPC itself). */ if (result != OSSO_OK) { g_error("Error launching the RPC (%s)\n", ossoErrorStr(result)); /* We also terminate right away since there's nothing to do. */ } g_print("RPC launched successfully\n"); g_print("launchRPC ending\n"); /* We only want to be called once, so ask the caller to remove this callback from the timer launch list by returning FALSE. */ return FALSE; } int main(int argc, char** argv) { /* Keep the application state in main's stack. */ ApplicationState state = {}; /* Keeps the results from LibOSSO functions for decoding. */ osso_return_t result; /* Default timeout for RPC calls in LibOSSO. */ gint rpcTimeout; g_print("Initializing LibOSSO\n"); state.ossoContext = osso_initialize(ProgName, "1.0", FALSE, NULL); if (state.ossoContext == NULL) { g_error("Failed to initialize LibOSSO\n"); } /* Print out the default timeout value (which we don't change, but could, with osso_rpc_set_timeout()). */ result = osso_rpc_get_timeout(state.ossoContext, &rpcTimeout); if (result != OSSO_OK) { g_error("Error getting default RPC timeout (%s)\n", ossoErrorStr(result)); } /* Interestingly the timeout seems to be -1, but is something else (by default). -1 probably then means that "no timeout has been set". */ g_print("Default RPC timeout is %d (units)\n", rpcTimeout); g_print("Creating a mainloop object\n"); /* Create a GMainLoop with default context and initial condition of not running (FALSE). */ state.mainloop = g_main_loop_new(NULL, FALSE); if (state.mainloop == NULL) { g_error("Failed to create a GMainLoop\n"); } g_print("Adding timeout to launch the RPC in one second\n"); /* This could be replaced by g_idle_add(cb, &state), in order to guarantee that the RPC would be launched only after the mainloop has started. We opt for a timeout here (for no particular reason). */ g_timeout_add(1000, (GSourceFunc)launchRPC, &state); g_print("Starting mainloop processing\n"); g_main_loop_run(state.mainloop); g_print("Out of mainloop, shutting down LibOSSO\n"); /* Deinitialize LibOSSO. */ osso_deinitialize(state.ossoContext); state.ossoContext = NULL; /* Free GMainLoop as well. */ g_main_loop_unref(state.mainloop); state.mainloop = NULL; g_print("Quitting\n"); return EXIT_SUCCESS; }
B.4 libosso-example-async/Makefile
libosso-example-async/Makefile# # Simple Makefile to build the LibOSSO/Async-RPC example # # Define a list of pkg-config packages we want to use pkg_packages := glib-2.0 libosso PKG_CFLAGS := $(shell pkg-config -cflags $(pkg_packages)) PKG_LDFLAGS := $(shell pkg-config -libs $(pkg_packages)) # Add warnings and debugging info ADD_CFLAGS += -g -Wall # Combine user supplied, additional, and pkg-config flags CFLAGS := $(PKG_CFLAGS) $(ADD_CFLAGS) $(CFLAGS) LDFLAGS := $(PKG_LDFLAGS) $(LDFLAGS) targets = libosso-rpc-async all: $(targets) libosso-rpc-async: libosso-rpc-async.c $(CC) $(CFLAGS) -DProgName=\"LibOSSOExample\" \ $< -o $@ $(LDFLAGS) .PHONY: clean all clean: $(RM) $(targets)
Improve this page