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

(Created page with '= Overview = LibOSSO is the basic library, containing required and helpful functions for Maemo applications. The full API documentation of LibOSSO is available in Doxygen format…')
(add ==Further reading==)
 
(10 intermediate revisions not shown)
Line 1: Line 1:
-
= Overview =
+
LibOSSO is the basic library, containing required and helpful functions for Maemo applications. The [http://maemo.org/api_refs/5.0/5.0-final/libosso/ full API documentation of LibOSSO is available] in Doxygen format.
-
LibOSSO is the basic library, containing required and helpful functions for Maemo applications. The full API documentation of LibOSSO is available in Doxygen format.
+
== Maemo initialization ==
-
 
+
-
= 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.
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 <code>osso_initialize()</code> function. With this function, the application connects to D-BUS session bus and system bus. <code>osso_initialize()</code> 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. <br />
+
Initializing application is performed with <code>osso_initialize()</code> function. With this function, the application connects to D-Bus session bus and system bus. <code>osso_initialize()</code> function should only be called once in the application, and the structure of type <code>osso_context_t</code> 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 <code>TRUE</code> 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, <code>NULL</code> should be used for the default context.
-
<br />''osso_context_t * osso_initialize(const gchar *application, const gchar* version, gboolean activation, GMainContext *context)''<br /><br /> 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. <br /><br />''void osso_deinitialize(osso_context_t *osso)''<br /><br />
+
<source lang="c">
 +
osso_context_t * osso_initialize(const gchar *application, const gchar* version, gboolean activation, GMainContext *context)
 +
</source>
-
Below is an example ([https://garage.maemo.org/svn/maemoexamples/trunk/maemo-examples/example_libosso.c example_libosso.c]) of this; if the initialization does not succeed, the function returns NULL.
+
When the application is closing, <code>osso_deinitialize</code> function should be called to close the message bus connection and free all memory allocated by the library.
-
<tt><span>'''<span><font color="#000080"><nowiki>#define</nowiki></font></span>'''</span> OSSO_EXAMPLE_NAME    <span><font color="#FF0000">"example_libosso"</font></span>
+
<source lang="c">
-
<span>'''<span><font color="#000080"><nowiki>#define</nowiki></font></span>'''</span> OSSO_EXAMPLE_SERVICE <span><font color="#FF0000">"org.maemo."</font></span>OSSO_EXAMPLE_NAME
+
void osso_deinitialize(osso_context_t *osso)
-
<span>''<span><font color="#9A1900">/* ... */</font></span>''</span>
+
</source>
-
    osso_context_t <span><font color="#990000"><nowiki>*</nowiki></font></span>osso_context<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
-
    <span>''<span><font color="#9A1900">/* ... */</font></span>''</span>
+
-
    <span>''<span><font color="#9A1900">/* Initialize maemo application */</font></span>''</span>
+
-
    osso_context <span><font color="#990000"><nowiki>=</nowiki></font></span> <span>'''<span><font color="#000000">osso_initialize</font></span>'''</span><span><font color="#990000">(</font></span>OSSO_EXAMPLE_SERVICE<span><font color="#990000">,</font></span> <span><font color="#FF0000">"0.0.1"</font></span><span><font color="#990000">,</font></span> TRUE<span><font color="#990000">,</font></span> NULL<span><font color="#990000">);</font></span>
+
-
    <span>''<span><font color="#9A1900">/* Check that initialization was ok */</font></span>''</span>
+
-
    <span>'''<span><font color="#0000FF">if</font></span>'''</span> <span><font color="#990000">(</font></span>osso_context <span><font color="#990000"><nowiki>==</nowiki></font></span> NULL<span><font color="#990000">)</font></span> <span><font color="#FF0000">{</font></span>
+
-
        <span>'''<span><font color="#0000FF">return</font></span>'''</span> OSSO_ERROR<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
-
    <span><font color="#FF0000">}</font></span>
+
-
    <span>''<span><font color="#9A1900">/* ... */</font></span>''</span>
+
-
    <span>''<span><font color="#9A1900">/* Deinitialize OSSO */</font></span>''</span>
+
-
    <span>'''<span><font color="#000000">osso_deinitialize</font></span>'''</span><span><font color="#990000">(</font></span>osso_context<span><font color="#990000">);</font></span>
+
-
</tt>
+
-
= Remote process messages =
+
Below is an example ([https://vcs.maemo.org/svn/maemoexamples/tags/maemo_5.0/maemo-examples/example_libosso.c example_libosso.c]) of this; if the initialization does not succeed, the function returns <code>NULL</code>.
-
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.
+
<source lang="c">
 +
#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);
 +
</source>
-
Callback function receiving the messages can be as follows ([https://garage.maemo.org/svn/maemoexamples/trunk/maemo-examples/example_libosso.c example_libosso.c]), where AppData structure contains the initialized osso_context:
+
== Remote process messages ==
-
<tt><span>'''<span><font color="#000080"><nowiki>#include</nowiki></font></span>'''</span> <span><font color="#FF0000">&lt;hildon/hildon-program.h&gt;</font></span>
+
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.
-
<span>'''<span><font color="#000080"><nowiki>#include</nowiki></font></span>'''</span> <span><font color="#FF0000">&lt;hildon/hildon-banner.h&gt;</font></span>
+
-
<span>'''<span><font color="#000080"><nowiki>#include</nowiki></font></span>'''</span> <span><font color="#FF0000">&lt;gtk/gtk.h&gt;</font></span>
+
-
<span>'''<span><font color="#000080"><nowiki>#include</nowiki></font></span>'''</span> <span><font color="#FF0000">&lt;libosso.h&gt;</font></span>
+
-
<span>'''<span><font color="#000080"><nowiki>#define</nowiki></font></span>'''</span> OSSO_EXAMPLE_NAME    <span><font color="#FF0000">"example_libosso"</font></span>
+
-
<span>'''<span><font color="#000080"><nowiki>#define</nowiki></font></span>'''</span> OSSO_EXAMPLE_SERVICE <span><font color="#FF0000">"org.maemo."</font></span>OSSO_EXAMPLE_NAME
+
-
<span>'''<span><font color="#000080"><nowiki>#define</nowiki></font></span>'''</span> OSSO_EXAMPLE_OBJECT  <span><font color="#FF0000">"/org/maemo/"</font></span>OSSO_EXAMPLE_NAME
+
-
<span>'''<span><font color="#000080"><nowiki>#define</nowiki></font></span>'''</span> OSSO_EXAMPLE_IFACE  <span><font color="#FF0000">"org.maemo."</font></span>OSSO_EXAMPLE_NAME
+
-
<span>''<span><font color="#9A1900">/* ... */</font></span>''</span>
+
-
<span>''<span><font color="#9A1900">/* Application UI data struct */</font></span>''</span>
+
-
<span>'''<span><font color="#0000FF">typedef</font></span>'''</span> <span>'''<span><font color="#0000FF">struct</font></span>'''</span> <span><font color="#009900">_AppData</font></span> AppData<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
-
<span>'''<span><font color="#0000FF">struct</font></span>'''</span> <span><font color="#009900">_AppData</font></span> <span><font color="#FF0000">{</font></span>
+
-
    HildonProgram <span><font color="#990000"><nowiki>*</nowiki></font></span>program<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
-
    HildonWindow <span><font color="#990000"><nowiki>*</nowiki></font></span>window<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
-
    osso_context_t <span><font color="#990000"><nowiki>*</nowiki></font></span>osso_context<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
-
<span><font color="#FF0000">}</font></span><span><font color="#990000"><nowiki>;</nowiki></font></span>
+
-
<span>''<span><font color="#9A1900">/* ... */</font></span>''</span>
+
-
<span>''<span><font color="#9A1900">/* Callback for normal D-BUS messages */</font></span>''</span>
+
-
gint <span>'''<span><font color="#000000">dbus_req_handler</font></span>'''</span><span><font color="#990000">(</font></span><span>'''<span><font color="#0000FF">const</font></span>'''</span> gchar <span><font color="#990000"><nowiki>*</nowiki></font></span> interface<span><font color="#990000">,</font></span> <span>'''<span><font color="#0000FF">const</font></span>'''</span> gchar <span><font color="#990000"><nowiki>*</nowiki></font></span> method<span><font color="#990000">,</font></span>
+
-
                      GArray <span><font color="#990000"><nowiki>*</nowiki></font></span> arguments<span><font color="#990000">,</font></span> gpointer data<span><font color="#990000">,</font></span>
+
-
                      osso_rpc_t <span><font color="#990000"><nowiki>*</nowiki></font></span> retval<span><font color="#990000">)</font></span>
+
-
<span><font color="#FF0000">{</font></span>
+
-
    AppData <span><font color="#990000"><nowiki>*</nowiki></font></span>appdata<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
-
    appdata <span><font color="#990000"><nowiki>=</nowiki></font></span> <span><font color="#990000">(</font></span>AppData <span><font color="#990000"><nowiki>*)</nowiki></font></span> data<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
-
    <span>'''<span><font color="#000000">osso_system_note_infoprint</font></span>'''</span><span><font color="#990000">(</font></span>appdata<span><font color="#990000">-&gt;</font></span>osso_context<span><font color="#990000">,</font></span> method<span><font color="#990000">,</font></span> retval<span><font color="#990000">);</font></span>
+
-
    <span>'''<span><font color="#000000">osso_rpc_free_val</font></span>'''</span><span><font color="#990000">(</font></span>retval<span><font color="#990000">);</font></span>
+
-
    <span>'''<span><font color="#0000FF">return</font></span>'''</span> OSSO_OK<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
-
<span><font color="#FF0000">}</font></span>
+
-
</tt>
+
-
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:
+
Callback function receiving the messages can be as follows ([https://vcs.maemo.org/svn/maemoexamples/tags/maemo_5.0/maemo-examples/example_libosso.c example_libosso.c]), where <code>AppData</code> structure contains the initialized <code>osso_context</code>:
-
<tt><span><font color="#009900">int</font></span> <span>'''<span><font color="#000000">main</font></span>'''</span><span><font color="#990000">(</font></span><span><font color="#009900">int</font></span> argc<span><font color="#990000">,</font></span> <span><font color="#009900">char</font></span> <span><font color="#990000"><nowiki>*</nowiki></font></span>argv<span><font color="#990000">[])</font></span>
+
<source lang="c">
-
<span><font color="#FF0000">{</font></span>
+
#include <hildon/hildon-program.h>
-
    osso_return_t result<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
#include <hildon/hildon-banner.h>
-
+
#include <gtk/gtk.h>
-
    <span>''<span><font color="#9A1900">/* ... */</font></span>''</span>
+
#include <libosso.h>
-
    <span>''<span><font color="#9A1900">/* Add handler for session bus D-BUS messages */</font></span>''</span>
+
#define OSSO_EXAMPLE_NAME    "example_libosso"
-
    result <span><font color="#990000"><nowiki>=</nowiki></font></span> <span>'''<span><font color="#000000">osso_rpc_set_cb_f</font></span>'''</span><span><font color="#990000">(</font></span>appdata<span><font color="#990000">-&gt;</font></span>osso_context<span><font color="#990000">,</font></span>
+
#define OSSO_EXAMPLE_SERVICE "org.maemo."OSSO_EXAMPLE_NAME
-
                                OSSO_EXAMPLE_SERVICE<span><font color="#990000">,</font></span>
+
#define OSSO_EXAMPLE_OBJECT  "/org/maemo/"OSSO_EXAMPLE_NAME
-
                                OSSO_EXAMPLE_OBJECT<span><font color="#990000">,</font></span>
+
#define OSSO_EXAMPLE_IFACE  "org.maemo."OSSO_EXAMPLE_NAME
-
                                OSSO_EXAMPLE_IFACE<span><font color="#990000">,</font></span>
+
/* ... */
-
                                dbus_req_handler<span><font color="#990000">,</font></span> appdata<span><font color="#990000">);</font></span>
+
/* Application UI data struct */
-
+
typedef struct _AppData AppData;
-
    <span>'''<span><font color="#0000FF">if</font></span>'''</span> <span><font color="#990000">(</font></span>result <span><font color="#990000"><nowiki>!=</nowiki></font></span> OSSO_OK<span><font color="#990000">)</font></span> <span><font color="#FF0000">{</font></span>
+
struct _AppData {
-
        <span>'''<span><font color="#000000">g_print</font></span>'''</span><span><font color="#990000">(</font></span><span><font color="#FF0000">"Error setting D-BUS callback (%d)</font></span><span><font color="#CC33CC">\n</font></span><span><font color="#FF0000">"</font></span><span><font color="#990000">,</font></span> result<span><font color="#990000">);</font></span>
+
    HildonProgram *program;
-
        <span>'''<span><font color="#0000FF">return</font></span>'''</span> OSSO_ERROR<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
    HildonWindow *window;
-
    <span><font color="#FF0000">}</font></span>
+
    osso_context_t *osso_context;
-
    <span>''<span><font color="#9A1900">/* ... */</font></span>''</span>
+
};
-
+
/* ... */
-
    <span>''<span><font color="#9A1900">/* Deinitialize OSSO */</font></span>''</span>
+
/* Callback for normal D-Bus messages */
-
    <span>'''<span><font color="#000000">osso_deinitialize</font></span>'''</span><span><font color="#990000">(</font></span>osso_context<span><font color="#990000">);</font></span>
+
gint dbus_req_handler(const gchar * interface, const gchar * method,
-
<span><font color="#FF0000">}</font></span>
+
                      GArray * arguments, gpointer data,
-
</tt>
+
                      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;
 +
}
 +
</source>
-
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 ([https://garage.maemo.org/svn/maemoexamples/trunk/maemo-examples/example_message.c example_message.c]<nowiki>), can send the ``HelloWorld'' that this application was designed to handle, as follows: </nowiki>
+
To attach this callback function to receive all the normal D-Bus messages to the application, use the <code>osso_rpc_set_default_cb_f</code> function as follows:
-
<tt><span>''<span><font color="#9A1900">/* ... */</font></span>''</span>
+
<source lang="c">
-
<span>'''<span><font color="#000080"><nowiki>#define</nowiki></font></span>'''</span> OSSO_EXAMPLE_NAME    <span><font color="#FF0000">"example_libosso"</font></span>
+
int main(int argc, char *argv[])
-
<span>'''<span><font color="#000080"><nowiki>#define</nowiki></font></span>'''</span> OSSO_EXAMPLE_SERVICE <span><font color="#FF0000">"org.maemo."</font></span>OSSO_EXAMPLE_NAME
+
{
-
<span>'''<span><font color="#000080"><nowiki>#define</nowiki></font></span>'''</span> OSSO_EXAMPLE_OBJECT  <span><font color="#FF0000">"/org/maemo/"</font></span>OSSO_EXAMPLE_NAME
+
    osso_return_t result;
-
<span>'''<span><font color="#000080"><nowiki>#define</nowiki></font></span>'''</span> OSSO_EXAMPLE_IFACE  <span><font color="#FF0000">"org.maemo."</font></span>OSSO_EXAMPLE_NAME
+
-
<span>'''<span><font color="#000080"><nowiki>#define</nowiki></font></span>'''</span> OSSO_EXAMPLE_MESSAGE <span><font color="#FF0000">"HelloWorld"</font></span>
+
-
<span>''<span><font color="#9A1900">/* ... */</font></span>''</span>
+
-
ret <span><font color="#990000"><nowiki>=</nowiki></font></span> <span>'''<span><font color="#000000">osso_rpc_run</font></span>'''</span><span><font color="#990000">(</font></span>osso_context<span><font color="#990000">,</font></span>
+
-
                    OSSO_EXAMPLE_SERVICE<span><font color="#990000">,</font></span>
+
-
                    OSSO_EXAMPLE_OBJECT<span><font color="#990000">,</font></span>
+
-
                    OSSO_EXAMPLE_IFACE<span><font color="#990000">,</font></span>
+
-
                    OSSO_EXAMPLE_MESSAGE<span><font color="#990000">,</font></span> <span><font color="#990000">&amp;</font></span>retval<span><font color="#990000">,</font></span> DBUS_TYPE_INVALID<span><font color="#990000">);</font></span>
+
-
<span>''<span><font color="#9A1900">/* ... */</font></span>''</span></tt>
+
-
<nowiki> 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. </nowiki>
+
    /* ... */
 +
    /* 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);
-
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!
+
    if (result != OSSO_OK) {
 +
        g_print("Error setting D-Bus callback (%d)\n", result);
 +
        return OSSO_ERROR;
 +
    }
 +
    /* ... */
-
=Hardware state messages =
+
    /* Deinitialize OSSO */
 +
    osso_deinitialize(osso_context);
 +
}
 +
</source>
-
<nowiki> 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. </nowiki>
+
Now the application is ready to receive D-Bus messages. Whenever it receives one, the <code>dbus_req_handler()</code> function is called to process the message. Another test application ([https://vcs.maemo.org/svn/maemoexamples/tags/maemo_5.0/maemo-examples/example_message.c example_message.c]), can send the ''HelloWorld'' that this application was designed to handle, as follows:
-
A callback function is defined like below, taking <code>osso_hw_state_t</code> and gpointer as parameters. The changed state can be gotten from state variable ([https://garage.maemo.org/svn/maemoexamples/trunk/maemo-examples/example_libosso.c <code>example_libosso.c</code>]).
+
<source lang="c">
 +
/* ... */
 +
#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);
 +
/* ... */
 +
</source>
-
<tt><span>''<span><font color="#9A1900">/* Callback for hardware D-BUS events */</font></span>''</span>
+
When example_libosso_test is started, it sends an <code>example_message</code> D-Bus message to <code>org.maemo.example_libosso</code> service, attached to the example_libosso application (See more about D-Bus service files from an earlier section). Now when <code>example_libosso</code> receives the message, it shows a banner.
-
<span><font color="#009900">void</font></span> <span>'''<span><font color="#000000">hw_event_handler</font></span>'''</span><span><font color="#990000">(</font></span>osso_hw_state_t <span><font color="#990000"><nowiki>*</nowiki></font></span>state<span><font color="#990000">,</font></span> gpointer data<span><font color="#990000">)</font></span>
+
 
-
<span><font color="#FF0000">{</font></span>
+
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!
-
    AppData <span><font color="#990000"><nowiki>*</nowiki></font></span>appdata<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
 
-
    appdata <span><font color="#990000"><nowiki>=</nowiki></font></span> <span><font color="#990000">(</font></span>AppData <span><font color="#990000"><nowiki>*)</nowiki></font></span> data<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
==Hardware state messages ==
-
    <span>'''<span><font color="#0000FF">if</font></span>'''</span> <span><font color="#990000">(</font></span>state<span><font color="#990000">-&gt;</font></span>shutdown_ind<span><font color="#990000">)</font></span>
+
 
-
    <span><font color="#FF0000">{</font></span>
+
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.
-
        <span>'''<span><font color="#000000">hildon_banner_show_information</font></span>'''</span><span><font color="#990000">(</font></span><span>'''<span><font color="#000000">GTK_WIDGET</font></span>'''</span><span><font color="#990000">(</font></span>appdata<span><font color="#990000">-&gt;</font></span>window<span><font color="#990000">),</font></span> NULL<span><font color="#990000">,</font></span>
+
 
-
                                        <span><font color="#FF0000">"Shutdown event!"</font></span><span><font color="#990000">);</font></span>
+
A callback function is defined like below, taking <code>osso_hw_state_t</code> and <code>gpointer</code> as parameters. The changed state can be gotten from state variable ([https://vcs.maemo.org/svn/maemoexamples/tags/maemo_5.0/maemo-examples/example_libosso.c <code>example_libosso.c</code>]).
-
    <span><font color="#FF0000">}</font></span>
+
 
-
    <span>'''<span><font color="#0000FF">if</font></span>'''</span> <span><font color="#990000">(</font></span>state<span><font color="#990000">-&gt;</font></span>memory_low_ind<span><font color="#990000">)</font></span>
+
<source lang="c">
-
    <span><font color="#FF0000">{</font></span>
+
/* Callback for hardware D-Bus events */
-
        <span>'''<span><font color="#000000">hildon_banner_show_information</font></span>'''</span><span><font color="#990000">(</font></span><span>'''<span><font color="#000000">GTK_WIDGET</font></span>'''</span><span><font color="#990000">(</font></span>appdata<span><font color="#990000">-&gt;</font></span>window<span><font color="#990000">),</font></span> NULL<span><font color="#990000">,</font></span>
+
void hw_event_handler(osso_hw_state_t *state, gpointer data)
-
                                        <span><font color="#FF0000">"Memory low event!"</font></span><span><font color="#990000">);</font></span>
+
{
-
    <span><font color="#FF0000">}</font></span>
+
    AppData *appdata;
-
    <span>'''<span><font color="#0000FF">if</font></span>'''</span> <span><font color="#990000">(</font></span>state<span><font color="#990000">-&gt;</font></span>save_unsaved_data_ind<span><font color="#990000">)</font></span>
+
    appdata = (AppData *) data;
-
    <span><font color="#FF0000">{</font></span>
+
    if (state->shutdown_ind)
-
        <span>'''<span><font color="#000000">hildon_banner_show_information</font></span>'''</span><span><font color="#990000">(</font></span><span>'''<span><font color="#000000">GTK_WIDGET</font></span>'''</span><span><font color="#990000">(</font></span>appdata<span><font color="#990000">-&gt;</font></span>window<span><font color="#990000">),</font></span> NULL<span><font color="#990000">,</font></span>
+
    {
-
                                        <span><font color="#FF0000">"Must save unsaved data event!"</font></span><span><font color="#990000">);</font></span>
+
        hildon_banner_show_information(GTK_WIDGET(appdata->window), NULL,
-
    <span><font color="#FF0000">}</font></span>
+
                                      "Shutdown event!");
-
    <span>'''<span><font color="#0000FF">if</font></span>'''</span> <span><font color="#990000">(</font></span>state<span><font color="#990000">-&gt;</font></span>system_inactivity_ind<span><font color="#990000">)</font></span>
+
    }
-
    <span><font color="#FF0000">{</font></span>
+
    if (state->memory_low_ind)
-
        <span>'''<span><font color="#000000">hildon_banner_show_information</font></span>'''</span><span><font color="#990000">(</font></span><span>'''<span><font color="#000000">GTK_WIDGET</font></span>'''</span><span><font color="#990000">(</font></span>appdata<span><font color="#990000">-&gt;</font></span>window<span><font color="#990000">),</font></span> NULL<span><font color="#990000">,</font></span>
+
    {
-
                                        <span><font color="#FF0000">"Minimize application inactivity event!"</font></span><span><font color="#990000">);</font></span>
+
        hildon_banner_show_information(GTK_WIDGET(appdata->window), NULL,
-
    <span><font color="#FF0000">}</font></span>
+
                                      "Memory low event!");
-
<span><font color="#FF0000">}</font></span></tt>
+
    }
 +
    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!");
 +
    }
 +
}
 +
</source>
To attach this handler, e.g. in application <code>main()</code>, use <code>osso_hw_set_event_cb()</code>.
To attach this handler, e.g. in application <code>main()</code>, use <code>osso_hw_set_event_cb()</code>.
-
<tt>    <span>''<span><font color="#9A1900">/* ... */</font></span>''</span>
+
<source lang="c">
-
+
    /* ... */
-
    <span>''<span><font color="#9A1900">/* Add handler for hardware D-BUS messages */</font></span>''</span>
+
-
    result <span><font color="#990000"><nowiki>=</nowiki></font></span> <span>'''<span><font color="#000000">osso_hw_set_event_cb</font></span>'''</span><span><font color="#990000">(</font></span> appdata<span><font color="#990000">-&gt;</font></span>osso_context<span><font color="#990000">,</font></span>
+
-
        NULL<span><font color="#990000">,</font></span> hw_event_handler<span><font color="#990000">,</font></span> <span><font color="#990000">(</font></span>gpointer<span><font color="#990000">)</font></span> appdata <span><font color="#990000">);</font></span>
+
-
+
-
    <span>'''<span><font color="#0000FF">if</font></span>'''</span> <span><font color="#990000">(</font></span>result <span><font color="#990000"><nowiki>!=</nowiki></font></span> OSSO_OK<span><font color="#990000">)</font></span>
+
-
    <span><font color="#FF0000">{</font></span>
+
-
        <span>'''<span><font color="#000000">g_print</font></span>'''</span><span><font color="#990000">(</font></span><span><font color="#FF0000">"Error setting HW state callback (%d)</font></span><span><font color="#CC33CC">\n</font></span><span><font color="#FF0000">"</font></span><span><font color="#990000">,</font></span> result<span><font color="#990000">);</font></span>
+
-
        <span>'''<span><font color="#0000FF">return</font></span>'''</span> OSSO_ERROR<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
-
    <span><font color="#FF0000">}</font></span>
+
-
+
-
    <span>''<span><font color="#9A1900">/* ... */</font></span>''</span></tt>
+
-
'''N.B.''' These hardware events are not sent to the SDK, so testing them is only possible in Maemo device.
+
    /* Add handler for hardware D-Bus messages */
 +
    result = osso_hw_set_event_cb( appdata->osso_context,
 +
        NULL, hw_event_handler, (gpointer) appdata );
-
= System Exit message =
+
    if (result != OSSO_OK)
 +
    {
 +
        g_print("Error setting HW state callback (%d)\n", result);
 +
        return OSSO_ERROR;
 +
    }
-
A system message is sent when applications are required to close themselves. Its callback is: ([https://garage.maemo.org/svn/maemoexamples/trunk/maemo-examples/example_libosso.c example_libosso.c]):
+
    /* ... */
 +
</source>
-
<tt><span>''<span><font color="#9A1900">/* Callback for exit D-BUS event */</font></span>''</span>
+
{{ambox
-
<span><font color="#009900">void</font></span> <span>'''<span><font color="#000000">exit_event_handler</font></span>'''</span><span><font color="#990000">(</font></span>gboolean die_now<span><font color="#990000">,</font></span> gpointer data<span><font color="#990000">)</font></span>
+
|text=These hardware events are not sent to the SDK, so testing them is only possible on a Maemo device.}}
-
<span><font color="#FF0000">{</font></span>
+
 
-
    AppData <span><font color="#990000"><nowiki>*</nowiki></font></span>appdata<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
== System Exit message ==
-
    appdata <span><font color="#990000"><nowiki>=</nowiki></font></span> <span><font color="#990000">(</font></span>AppData <span><font color="#990000"><nowiki>*)</nowiki></font></span> data<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
 
-
    <span>'''<span><font color="#000000">g_print</font></span>'''</span><span><font color="#990000">(</font></span><span><font color="#FF0000">"exit_event_handler called</font></span><span><font color="#CC33CC">\n</font></span><span><font color="#FF0000">"</font></span><span><font color="#990000">);</font></span>
+
A system message is sent when applications are required to close themselves. Its callback is: ([https://vcs.maemo.org/svn/maemoexamples/tags/maemo_5.0/maemo-examples/example_libosso.c example_libosso.c]):
-
    <span>''<span><font color="#9A1900">/* Do whatever application needs to do before exiting */</font></span>''</span>
+
 
-
    <span>'''<span><font color="#000000">hildon_banner_show_information</font></span>'''</span><span><font color="#990000">(</font></span><span>'''<span><font color="#000000">GTK_WIDGET</font></span>'''</span><span><font color="#990000">(</font></span>appdata<span><font color="#990000">-&gt;</font></span>window<span><font color="#990000">),</font></span> NULL<span><font color="#990000">,</font></span>
+
<source lang="c">
-
                                    <span><font color="#FF0000">"Exiting..."</font></span><span><font color="#990000">);</font></span>
+
/* Callback for exit D-Bus event */
-
<span><font color="#FF0000">}</font></span></tt>
+
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...");
 +
}
 +
</source>
The callback is set (e.g. in application main) as follows.
The callback is set (e.g. in application main) as follows.
-
<tt><span><font color="#009900">int</font></span> <span>'''<span><font color="#000000">main</font></span>'''</span><span><font color="#990000">(</font></span> <span><font color="#009900">int</font></span> argc<span><font color="#990000">,</font></span> <span><font color="#009900">char</font></span><span><font color="#990000"><nowiki>*</nowiki></font></span> argv<span><font color="#990000">[]</font></span> <span><font color="#990000">)</font></span>
+
<source lang="c">
-
<span><font color="#FF0000">{</font></span>
+
int main( int argc, char* argv[] )
-
<span>''<span><font color="#9A1900">/* ... */</font></span>''</span>
+
{
-
    <span>''<span><font color="#9A1900">/* Add handler for Exit D-BUS messages */</font></span>''</span>
+
/* ... */
-
    result <span><font color="#990000"><nowiki>=</nowiki></font></span> <span>'''<span><font color="#000000">osso_application_set_exit_cb</font></span>'''</span><span><font color="#990000">(</font></span>appdata<span><font color="#990000">-&gt;</font></span>osso_context<span><font color="#990000">,</font></span>
+
    /* Add handler for Exit D-BUS messages */
-
                                          exit_event_handler<span><font color="#990000">,</font></span>
+
    result = osso_application_set_exit_cb(appdata->osso_context,
-
                                          <span><font color="#990000">(</font></span>gpointer<span><font color="#990000">)</font></span> appdata<span><font color="#990000">);</font></span>
+
                                          exit_event_handler,
-
    <span>'''<span><font color="#0000FF">if</font></span>'''</span> <span><font color="#990000">(</font></span>result <span><font color="#990000"><nowiki>!=</nowiki></font></span> OSSO_OK<span><font color="#990000">)</font></span> <span><font color="#FF0000">{</font></span>
+
                                          (gpointer) appdata);
-
        <span>'''<span><font color="#000000">g_print</font></span>'''</span><span><font color="#990000">(</font></span><span><font color="#FF0000">"Error setting exit callback (%d)</font></span><span><font color="#CC33CC">\n</font></span><span><font color="#FF0000">"</font></span><span><font color="#990000">,</font></span> result<span><font color="#990000">);</font></span>
+
    if (result != OSSO_OK) {
-
        <span>'''<span><font color="#0000FF">return</font></span>'''</span> OSSO_ERROR<span><font color="#990000"><nowiki>;</nowiki></font></span>
+
        g_print("Error setting exit callback (%d)\n", result);
-
    <span><font color="#FF0000">}</font></span>
+
        return OSSO_ERROR;
-
<span>''<span><font color="#9A1900">/* ... */</font></span>''</span>
+
    }
-
<span><font color="#FF0000">}</font></span></tt>
+
/* ... */
 +
}
 +
</source>
Now whenever the system needs to close an application for any reason, the close is performed gracefully.
Now whenever the system needs to close an application for any reason, the close is performed gracefully.
-
= Application state saving and auto save =
+
== 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.
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.
Line 201: Line 221:
Information on how to implement state saving can be found in LibOSSO API document.
Information on how to implement state saving can be found in LibOSSO API document.
 +
 +
== Further reading ==
 +
 +
* [[Documentation/Maemo 5 Developer Guide/DBus/DBus Basics|Introduction to D-Bus]]
 +
 +
[[Category:Development]]
 +
[[Category:Documentation]]
 +
[[Category:Fremantle]]

Latest revision as of 10:43, 2 September 2010

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