I guess I'll release this later today. Is that ok with everyone?
[pidgin-git.git] / doc / SIGNAL-HOWTO.dox
blob3007415ca20f7764be94340742d2aded588c5d15
1 /** @page signal-howto Signals HOWTO
3  @section Introduction
4   The libpurple signals interface is used for general event notification, such
5   as plugins being loaded or unloaded, allowing the GUI frontend to respond
6   appropriately to changing internal data. Unfortunately, its use is not at all
7   obvious from the information in the header files. This document uses code
8   snippets from the Pidgin/libpurple plugin systems to illustrate the proper
9   use of signals.
11  @section overview Overview of Signals
12   Signals in libpurple are very similar to those in GTK+. When certain events
13   happen, a named signal is "emitted" from a certain object. Emitting the
14   signal triggers a series of callbacks that have been "connected" to that
15   signal for that object. These callbacks take appropriate action in response
16   to the signal.
18  @section registering_signal Registering a Signal
19   The first step of using a signal is registering it with libpurple so that
20   callbacks may be connected to it. This is done using purple_signal_register()
21   Here is a slightly modified example from @c purple_plugins_init in 
22   @c libpurple/plugin.c :
24   @code
25         purple_signal_register( purple_plugins_get_handle(), /* Instance */
26                                 "plugin-load",               /* Signal name */
27                                 purple_marshal_VOID__POINTER,/* Marshal function */
28                                 NULL,                        /* Callback return value type */
29                                 1,                           /* Number of callback arguments (not including void *data) */
30                                 purple_value_new(PURPLE_TYPE_SUBTYPE,PURPLE_SUBTYPE_PLUGIN) /* Type of first callback argument */
31                                 );
32   @endcode
34   @subsection Instance
35   A reference to the object from which this signal is emitted, and to which
36   potential callbacks should be connected. In this case, it will be the entire
37   plugin module emitting the signal.
38   
39   @subsection signalname Signal Name
40   Unique identifier for the signal itself.
42   @subsection therest Callback function definition
43   The rest of the arguments specify the form of the callback function.
45   @subsubsection marshalfunc Marshal Function
46   @c purple_marshal_VOID__POINTER represents the callback function prototype,
47   not including a "data" argument, explained later. The form is 
48   @c purple_marshal_RETURNVALUETYPE__ARG1TYPE_ARG2TYPE_ETC. See signals.h for
49   more possible types.
51   In this case, the callback will have the form
52   @code
53         void cb(void *arg1, void *data)
54   @endcode
56   If @c purple_marshal_BOOLEAN__POINTER_POINTER_POINTER were specified, it
57   would be:
58   @code
59         gboolean cb(void *arg1, void *arg2, void *arg3, void *data)
60   @endcode
62   The @c void @c *data argument at the end of each callback function
63   provides the data argument given to purple_signal_connect() .
65   @subsubsection cb_ret_type Callback return value type
66   In our case, this is NULL, meaning "returns void".
67   @todo This could be described better.
69   @subsubsection num_args Number of arguments
70   The number of arguments (not including @c data ) that the callback function
71   will take.
73   @subsubsection type_arg Type of argument
74   @c purple_value_new(PURPLE_TYPE_SUBTYPE,PURPLE_SUBTYPE_PLUGIN) specifies that
75   the first argument given to the callback will be a @c PurplePlugin* . You
76   will need as many "type of argument" arguments to purple_signal_register() as
77   you specified in "Number of arguments" above.
79   @todo Describe this more.
81   @see value.h
83   @section connect Connecting to the signal
84   Once the signal is registered, you can connect callbacks to it. First, you
85   must define a callback function, such as this one from gtkplugin.c :
86   @code
87 static void plugin_load_cb(PurplePlugin *plugin, gpointer data)
89         GtkTreeView *view = (GtkTreeView *)data;
90         plugin_loading_common(plugin, view, TRUE);
92   @endcode
93   Note that the callback function prototype matches that specified in the call
94   to purple_signal_register() above.
96   Once the callback function is defined, you can connect it to the signal.
97   Again from gtkplugin.c , in @c pidgin_plugin_dialog_show() :
98   @code
99         purple_signal_connect(purple_plugins_get_handle(), "plugin-load", /* What to connect to */
100                 plugin_dialog, /* Object receiving the signal */
101                 PURPLE_CALLBACK(plugin_load_cb), /* Callback function */
102                 event_view, /* Data to pass to the callback function
103                 );
104   @endcode
106   The first two arguments ("What to connect to") specify the object emitting
107   the signal (the plugin module) and what signal to listen for ("plugin-load").
109   The object receiving the signal is @c plugin_dialog , the Pidgin plugins
110   dialog. When @c plugin_dialog is deleted, then 
111   @c purple_signals_disconnect_by_handle(plugin_dialog) should be called to
112   remove all signal connections it is associated with.
114   The callback function is given using a helper macro, and finally the
115   @c data argument to be passed to @c plugin_load_cb is given as @c event_view,
116   a pointer to the GTK widget that @c plugin_load_cb needs to update.
118   @section emit-signal Emitting a signal
119   Connecting callbacks to signals is all well and good, but how do you "fire"
120   the signal and trigger the callback? At some point, you must "emit" the
121   signal, which immediately calls all connected callbacks.
123   As seen in @c purple_plugin_load() in plugin.c :
124   @code
125         purple_signal_emit(purple_plugins_get_handle(), "plugin-load", plugin);
126   @endcode
127   This causes the signal "plugin-load" to be emitted from the plugin module
128   (given by @c purple_plugins_get_handle() ), with the newly loaded plugin as
129   the argument to pass to any registered callback functions.
131   In our example, @c plugin_load_cb is called immediately as
132   @code
133         plugin_load_cb(plugin, event_view);
134   @endcode
135   and does whatever it does.
136   
137  */