1 /** @page signal-howto Signals HOWTO
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
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
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 :
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 */
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.
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
51 In this case, the callback will have the form
53 void cb(void *arg1, void *data)
56 If @c purple_marshal_BOOLEAN__POINTER_POINTER_POINTER were specified, it
59 gboolean cb(void *arg1, void *arg2, void *arg3, void *data)
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
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.
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 :
87 static void plugin_load_cb(PurplePlugin *plugin, gpointer data)
89 GtkTreeView *view = (GtkTreeView *)data;
90 plugin_loading_common(plugin, view, TRUE);
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() :
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
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 :
125 purple_signal_emit(purple_plugins_get_handle(), "plugin-load", plugin);
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
133 plugin_load_cb(plugin, event_view);
135 and does whatever it does.