Documentation/Maemo 5 Developer Guide/Application Development/LibOSSO library

LibOSSO is the basic library, containing required and helpful functions for Maemo applications. The full API documentation of LibOSSO is available in Doxygen format.

Contents

[edit] Maemo initialization

All Maemo applications must be initialized correctly, or they do not work as expected. One symptom of missing initialization is that application starts from Task Navigator, but closes automatically after few seconds.

Initializing application is performed with osso_initialize() function. With this function, the application connects to D-Bus session bus and system bus. osso_initialize() function should only be called once in the application, and the structure of type osso_context_t type that is returned should be stored for later use. First parameter of the function is the application D-Bus name, used also in application D-Bus service file. Second parameter is the application version as a string. Third is the activation type, with TRUE the library assumes that the application binary has been launched by the D-Bus daemon, and thus connects to the D-Bus activation bus. Fourth parameter is the GLib main-loop context to connect to, NULL should be used for the default context.

osso_context_t * osso_initialize(const gchar *application, const gchar* version, gboolean activation, GMainContext *context)

When the application is closing, osso_deinitialize function should be called to close the message bus connection and free all memory allocated by the library.

void osso_deinitialize(osso_context_t *osso)

Below is an example (example_libosso.c) of this; if the initialization does not succeed, the function returns NULL.

#define OSSO_EXAMPLE_NAME    "example_libosso"
#define OSSO_EXAMPLE_SERVICE "org.maemo."OSSO_EXAMPLE_NAME
/* ... */
    osso_context_t *osso_context;
    /* ... */
    /* Initialize maemo application */
    osso_context = osso_initialize(OSSO_EXAMPLE_SERVICE, "0.0.1", TRUE, NULL);
    /* Check that initialization was ok */
    if (osso_context == NULL) {
        return OSSO_ERROR;
    }
    /* ... */
    /* Deinitialize OSSO */
    osso_deinitialize(osso_context);

[edit] Remote process messages

System wide messages in Maemo platform are handled with D-Bus system messaging, which is a Remote Process Communication (RPC) method. LibOSSO has own wrappers to normal D-Bus functions to make usage simpler and to maintain backward compatibility. By using D-Bus, applications can send messages from one process to another.

Callback function receiving the messages can be as follows (example_libosso.c), where AppData structure contains the initialized osso_context:

#include <hildon/hildon-program.h>
#include <hildon/hildon-banner.h>
#include <gtk/gtk.h>
#include <libosso.h>
#define OSSO_EXAMPLE_NAME    "example_libosso"
#define OSSO_EXAMPLE_SERVICE "org.maemo."OSSO_EXAMPLE_NAME
#define OSSO_EXAMPLE_OBJECT  "/org/maemo/"OSSO_EXAMPLE_NAME
#define OSSO_EXAMPLE_IFACE   "org.maemo."OSSO_EXAMPLE_NAME
/* ... */
/* Application UI data struct */
typedef struct _AppData AppData;
struct _AppData {
    HildonProgram *program;
    HildonWindow *window;
    osso_context_t *osso_context;
};
/* ... */
/* Callback for normal D-Bus messages */
gint dbus_req_handler(const gchar * interface, const gchar * method,
                      GArray * arguments, gpointer data,
                      osso_rpc_t * retval)
{
    AppData *appdata;
    appdata = (AppData *) data;
    osso_system_note_infoprint(appdata->osso_context, method, retval);
    osso_rpc_free_val(retval);
    return OSSO_OK;
}

To attach this callback function to receive all the normal D-Bus messages to the application, use the osso_rpc_set_default_cb_f function as follows:

int main(int argc, char *argv[])
{
    osso_return_t result;
 
    /* ... */
    /* Add handler for session bus D-Bus messages */
    result = osso_rpc_set_cb_f(appdata->osso_context,
                               OSSO_EXAMPLE_SERVICE,
                               OSSO_EXAMPLE_OBJECT,
                               OSSO_EXAMPLE_IFACE,
                               dbus_req_handler, appdata);
 
    if (result != OSSO_OK) {
        g_print("Error setting D-Bus callback (%d)\n", result);
        return OSSO_ERROR;
    }
    /* ... */
 
    /* Deinitialize OSSO */
    osso_deinitialize(osso_context);
}

Now the application is ready to receive D-Bus messages. Whenever it receives one, the dbus_req_handler() function is called to process the message. Another test application (example_message.c), can send the HelloWorld that this application was designed to handle, as follows:

/* ... */
#define OSSO_EXAMPLE_NAME    "example_libosso"
#define OSSO_EXAMPLE_SERVICE "org.maemo."OSSO_EXAMPLE_NAME
#define OSSO_EXAMPLE_OBJECT  "/org/maemo/"OSSO_EXAMPLE_NAME
#define OSSO_EXAMPLE_IFACE   "org.maemo."OSSO_EXAMPLE_NAME
#define OSSO_EXAMPLE_MESSAGE "HelloWorld"
/* ... */
ret = osso_rpc_run(osso_context,
                   OSSO_EXAMPLE_SERVICE,
                   OSSO_EXAMPLE_OBJECT,
                   OSSO_EXAMPLE_IFACE,
                   OSSO_EXAMPLE_MESSAGE, &retval, DBUS_TYPE_INVALID);
/* ... */

When example_libosso_test is started, it sends an example_message D-Bus message to org.maemo.example_libosso service, attached to the example_libosso application (See more about D-Bus service files from an earlier section). Now when example_libosso receives the message, it shows a banner.

One nice thing about D-Bus is that the receiving application does not even need to be started: D-Bus can automatically start the application based on its service file, and then pass the message to it!

[edit] Hardware state messages

Maemo applications can connect to listen the system D-Bus messages, like battery low and shutdown. When these messages are received, the application may want to ask the user to save files that are open, or react however wanted.

A callback function is defined like below, taking osso_hw_state_t and gpointer as parameters. The changed state can be gotten from state variable (example_libosso.c).

/* Callback for hardware D-Bus events */
void hw_event_handler(osso_hw_state_t *state, gpointer data)
{
    AppData *appdata;
    appdata = (AppData *) data;
    if (state->shutdown_ind)
    {
        hildon_banner_show_information(GTK_WIDGET(appdata->window), NULL,
                                       "Shutdown event!");
    }
    if (state->memory_low_ind)
    {
        hildon_banner_show_information(GTK_WIDGET(appdata->window), NULL,
                                       "Memory low event!");
    }
    if (state->save_unsaved_data_ind)
    {
        hildon_banner_show_information(GTK_WIDGET(appdata->window), NULL,
                                       "Must save unsaved data event!");
    }
    if (state->system_inactivity_ind)
    {
        hildon_banner_show_information(GTK_WIDGET(appdata->window), NULL,
                                       "Minimize application inactivity event!");
    }
}

To attach this handler, e.g. in application main(), use osso_hw_set_event_cb().

    /* ... */
 
    /* Add handler for hardware D-Bus messages */
    result = osso_hw_set_event_cb( appdata->osso_context,
        NULL, hw_event_handler, (gpointer) appdata );
 
    if (result != OSSO_OK)
    {
        g_print("Error setting HW state callback (%d)\n", result);
        return OSSO_ERROR;
    }
 
    /* ... */
Image:Ambox_notice.png
These hardware events are not sent to the SDK, so testing them is only possible on a Maemo device.

[edit] System Exit message

A system message is sent when applications are required to close themselves. Its callback is: (example_libosso.c):

/* Callback for exit D-Bus event */
void exit_event_handler(gboolean die_now, gpointer data)
{
    AppData *appdata;
    appdata = (AppData *) data;
    g_print("exit_event_handler called\n");
    /* Do whatever application needs to do before exiting */
    hildon_banner_show_information(GTK_WIDGET(appdata->window), NULL,
                                   "Exiting...");
}

The callback is set (e.g. in application main) as follows.

int main( int argc, char* argv[] )
{
/* ... */
    /* Add handler for Exit D-BUS messages */
    result = osso_application_set_exit_cb(appdata->osso_context,
                                          exit_event_handler,
                                          (gpointer) appdata);
    if (result != OSSO_OK) {
        g_print("Error setting exit callback (%d)\n", result);
        return OSSO_ERROR;
    }
/* ... */
}

Now whenever the system needs to close an application for any reason, the close is performed gracefully.

[edit] Application state saving and auto save

State saving is a special feature of the Maemo platform. It means that applications save their running state from RAM to permanent memory, such as flash memory, and then end the running application process. This state saving happens when switching out from the application and the device memory is running low. When the user then returns to a backgrounded application, the application restarts, the application state is read from flash memory, and the user does not even know that the application was not running all the time.

Auto saving is an addition to state saving for editor-like applications containing user data. This data/document is automatically saved at the same time with state save. The main difference is that the application state is usually just a small amount of variables describing the state where the application was, whereas the auto-saved file can be any file the user was editing. Auto saving guarantees that user files are not lost when e.g. the battery runs out.

Information on how to implement state saving can be found in LibOSSO API document.

[edit] Further reading