Wed, 22 Mar 2006 06:56:41 +0000
[gaim-migrate @ 15926]
Kevin suggested this on gaim-devel:
'I would suggest changing "_Only when someone says your nick" in the
message notification plugin to a more standard terminology for your own
name or screen name or nickname. "Nick" is an IRC abbreviation which
may be less clear.
Kevin'
| 10468 | 1 | /** @page c-howto C Plugin HOWTO |
| 2 | ||
| 3 | @section Introduction | |
| 4 | C plugins are native plugins. They have complete access to all of the api, | |
| 5 | and can do basically whatever they want. All of the protocol plugins, as | |
| 6 | well as the perl and tcl loader plugins are written in C. | |
| 7 | ||
| 8 | @section getting_started Getting Started | |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
9 | To develop a plugin you need to have the Gaim source code. It is generally a |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
10 | good idea to compile against the same version of Gaim that you are running. |
| 10468 | 11 | You may also want to develop against CVS. While we do NOT recomend this for |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
12 | normal users, it makes sense for plugin developers to use CVS to ensure their |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
13 | plugins works with the most recent changes in Gaim. A lot tends to |
| 10468 | 14 | change between versions and it's much easier to fix your plugin as things |
| 15 | change rather than waiting until the release. But please do not abuse CVS. | |
| 16 | Gaim puts a lot of strain on Source Forge's servers, and we do not need to | |
| 17 | add anymore to it. | |
| 18 | ||
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
19 | If you choose not to head my warnings and develop against a version of Gaim |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
20 | that is different from what you're running, then your Gaim source must at |
| 10468 | 21 | the very least be configured. Note that just running configure will |
| 22 | generally set the prefix to /usr/local. This shouldn't be a problem, except | |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
23 | that most packages compile and install Gaim with /usr as the prefix. |
| 10468 | 24 | |
| 25 | All plugins must have @c GAIM_PLUGINS defined. You can choose to include | |
| 26 | @c internal.h to do this, but if you choose to do it this way it must be | |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
27 | included before any other Gaim files. Likewise, if you choose to manually |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
28 | define @c GAIM_PLUGINS, the definition must be before including any Gaim |
| 10468 | 29 | files. Failure to do so will produce the 'plugin foo could not be loaded for |
| 30 | an unknown reason'. This is one of the hardest unknown reasons to track | |
| 31 | down, so let's try to avoid it at all costs ;) | |
| 32 | ||
| 33 | @section hello_world Hello World! | |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
34 | I know every tutorial has a hello world, so why should Gaim be any different? |
| 10468 | 35 | |
| 36 | @code | |
| 37 | #define GAIM_PLUGINS | |
| 38 | ||
| 39 | #include <glib.h> | |
| 40 | ||
| 41 | #include "notify.h" | |
| 42 | #include "plugin.h" | |
| 43 | #include "version.h" | |
| 44 | ||
| 45 | static gboolean | |
| 46 | plugin_load(GaimPlugin *plugin) { | |
| 47 | gaim_notify_message(plugin, GAIM_NOTIFY_MSG_INFO, "Hello World!", | |
| 48 | "This is the Hello World! plugin :)", NULL, NULL, NULL); | |
| 49 | ||
| 50 | return TRUE; | |
| 51 | } | |
| 52 | ||
| 53 | static GaimPluginInfo info = { | |
| 54 | GAIM_PLUGIN_MAGIC, | |
| 55 | GAIM_MAJOR_VERSION, | |
| 56 | GAIM_MINOR_VERSION, | |
| 57 | GAIM_PLUGIN_STANDARD, | |
| 58 | NULL, | |
| 59 | 0, | |
| 60 | NULL, | |
| 61 | GAIM_PRIORITY_DEFAULT, | |
| 62 | ||
| 63 | "core-hello_world", | |
| 64 | "Hello World!", | |
| 65 | VERSION, | |
| 66 | ||
| 67 | "Hello World Plugin", | |
| 68 | "Hello World Plugin", | |
| 69 | NULL, | |
| 70 | GAIM_WEBSITE, | |
| 71 | ||
| 72 | plugin_load, | |
| 73 | NULL, | |
| 74 | NULL, | |
| 75 | ||
| 76 | NULL, | |
| 77 | NULL, | |
| 78 | NULL, | |
| 79 | NULL | |
| 80 | }; | |
| 81 | ||
| 82 | static void | |
| 83 | init_plugin(GaimPlugin *plugin) { | |
| 84 | } | |
| 85 | ||
| 86 | GAIM_INIT_PLUGIN(hello_world, init_plugin, info); | |
| 87 | ||
| 88 | @endcode | |
| 89 | ||
| 90 | Okay, so what does all this mean? We start off by defining @c GAIM_PLUGINS | |
| 91 | like described before. Next we include glib.h, mainly for gboolean and the | |
| 92 | glib wrappers of the standard c types. We could just use stdio and use | |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
93 | an int for the gboolean but since Gaim uses glib internally, we might as |
| 10468 | 94 | well do the same. |
| 95 | ||
| 96 | Next, we include plugin.h which has all the plugin specific stuff that we | |
| 97 | need. For example @c GaimPlugin, @c GaimPluginInfo, @c GAIM_PLUGIN_MAGIC, | |
| 98 | and @c GAIM_INIT_PLUGIN(). | |
| 99 | ||
| 100 | Our last include is version.h which defines @c GAIM_MAJOR_VERSION, and | |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
101 | @c GAIM_MINOR_VERSION. There is not much you need to know about these, |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
102 | except that they are required and will stop your plugin from crashing Gaim |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
103 | when something has changed that you plugin does not know about yet. |
| 10468 | 104 | |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
105 | plugin_load is not required. It is called when the plugin is loaded so that |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
106 | you can initialize any variables and so on. But in this plugin we'll just |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
107 | use it to display a message. |
| 10468 | 108 | |
| 109 | Next we have the @c GaimPluginInfo structure. Every plugin MUST have one of | |
| 110 | these. Below is a code snipet of the same struct used in @c hello_world with | |
| 111 | comments describing what each is. | |
| 112 | ||
| 113 | @code | |
| 114 | static GaimPluginInfo info = { | |
| 115 | GAIM_PLUGIN_MAGIC, /* Plugin magic, this should always be | |
| 116 | GAIM_PLUGIN_MAGIC. This value gets | |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
117 | incremented inside of Gaim so that plugins |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
118 | that haven't been updated yet will fail to |
| 10468 | 119 | load and avoid potential crashes while |
| 120 | loading old plugins. | |
| 121 | */ | |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
122 | GAIM_MAJOR_VERSION, /* This is also defined in Gaim. It helps |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
123 | Gaim's plugin system determine what version |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
124 | of Gaim this plugin was compiled for, and |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
125 | whether loading it will cause problems. |
| 10468 | 126 | */ |
| 127 | GAIM_MINOR_VERSION, /* See previous */ | |
| 128 | GAIM_PLUGIN_STANDARD, /* GaimPluginType, there are 4 different values | |
| 129 | for this field. The first is | |
| 130 | GAIM_PLUGIN_UNKNOWN, which should not be | |
| 131 | used. The second is GAIM_PLUGIN_STANDARD, | |
| 132 | this is the value most plugins will use. | |
| 133 | Next we have GAIM_PLUGIN_LOADER, this is | |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
134 | the type you want to load if your plugin |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
135 | is going to make it possible to load non- |
| 10468 | 136 | native plugins. For example, perl and tcl. |
| 137 | Last, we have GAIM_PLUGIN_PROTOCOL. If | |
| 138 | your plugin is going to allow the user to | |
| 139 | connect to another network, this is the | |
| 140 | type you'd want to use. | |
| 141 | */ | |
| 142 | NULL, /* This field is the ui requirement. This | |
| 143 | value should be a string. If you're | |
| 144 | writing a core plugin, this should be NULL | |
| 145 | and the plugin should not contain any ui | |
| 146 | specific code. If you're writing a gtk | |
| 147 | plugin, you can use the | |
| 148 | GAIM_GTK_PLUGIN_TYPE macro. All other ui | |
| 149 | plugins are dependent on their ui | |
| 150 | implementation, and is outside the scope of | |
| 151 | this howto. | |
| 152 | */ | |
| 153 | 0, /* This field is for plugin flags. Currently, | |
| 154 | the only flag available to plugins is | |
| 155 | invisible (GAIM_PLUGIN_FLAG_INVISIBLE). | |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
156 | This plugin is currently used by the ssl |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
157 | plugin, the tcl loader, and the perl |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
158 | loaded. It causes the plugin to NOT |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
159 | appear in the list of plugins in Gaim's |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
160 | preferences window. |
| 10468 | 161 | */ |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
162 | NULL, /* This is a GList of plugin dependencies. In |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
163 | other words, a GList of plugin id's that |
| 10468 | 164 | your plugin depends on. If your plugin |
| 165 | does not have any dependencies, set this | |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
166 | value to NULL. |
| 10468 | 167 | */ |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
168 | GAIM_PRIORITY_DEFAULT, /* This is the priority Gaim with give your |
| 10468 | 169 | plugin. There are three possible values |
| 170 | for this field, GAIM_PRIORITY_DEFAULT, | |
| 171 | GAIM_PRIORITY_HIGHEST, and | |
| 172 | GAIM_PRIORITY_LOWEST | |
| 173 | */ | |
| 174 | ||
| 175 | "core-hello_world", /* This is your plugin's id. There is a whole | |
| 176 | page dedicated to this in the | |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
177 | 'related-pages' section of Gaim's API docs. |
| 10468 | 178 | */ |
| 179 | "Hello World!", /* This is your plugin name. This is what | |
| 180 | will be displayed for your plugin in the ui. | |
| 181 | */ | |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
182 | 1.1, /* This is the version of your plugin. For |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
183 | the sake of simplicity, I'm using the Gaim |
| 10468 | 184 | version. |
| 185 | */ | |
| 186 | ||
| 187 | "Hello World Plugin", /* This is the summary of your plugin. It | |
| 188 | should be a short little blurb. The ui | |
| 189 | determines where, if at all, to display | |
| 190 | this. | |
| 191 | */ | |
| 192 | "Hello World Plugin", /* This is the description of your plugin. It | |
| 193 | can be as long and as descriptive as you | |
| 194 | like. And like the summary, it's up to the | |
| 195 | ui where, if at all, to display this. | |
| 196 | */ | |
| 197 | NULL, /* This is where you can put your name and | |
| 198 | email address. (You are the author right?) | |
| 199 | */ | |
| 200 | GAIM_WEBSITE, /* This is the website for the plugin. This | |
| 201 | is helpful if users find bugs in your | |
| 202 | plugin so they can help to bring them to | |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
203 | your attention. |
| 10468 | 204 | */ |
| 205 | ||
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
206 | plugin_load, /* This is a pointer to a function for Gaim to |
| 10468 | 207 | call when it is loading your plugin. It |
| 208 | should be in the form of: | |
| 209 | ||
| 210 | gboolean function_name(GaimPlugin *plugin) | |
| 211 | ||
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
212 | Returning TRUE will tell Gaim to continue |
| 10468 | 213 | loading your plugin, while FALSE will tell |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
214 | Gaim to stop trying to load it. |
| 10468 | 215 | */ |
| 216 | NULL, /* Same as above except it is called when | |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
217 | Gaim tries to unload your plugin. It |
| 10468 | 218 | should be in the form of: |
| 219 | ||
| 220 | gboolean function_name(GaimPlugin *plugin) | |
| 221 | ||
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
222 | Where returning TRUE will tell Gaim to |
| 10468 | 223 | continue unloading and false to not continue |
| 224 | unloading your plugin. | |
| 225 | */ | |
| 226 | NULL, /* Similar to the two above members, except | |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
227 | this is called when Gaim tries to destory |
| 10468 | 228 | the plugin. This is generally only called |
| 229 | when for some reason or another the plugin | |
| 230 | fails to probe correctly. It should be in | |
| 231 | the form of: | |
| 232 | ||
| 233 | void function_name(GaimPlugin *plugin) | |
| 234 | */ | |
| 235 | ||
| 236 | NULL, /* This is a pointer to a ui specific struct. | |
| 237 | For a gtk plugin it will be a pointer to a | |
| 238 | GaimGtkPluginUiInfo struct. | |
| 239 | */ | |
| 240 | NULL, /* This is a pointer to either a | |
| 241 | GaimPluginLoaderInfo struct or a | |
| 242 | GaimPluginProtocolInfo struct, and is | |
| 243 | beyond the scope of this document. | |
| 244 | */ | |
| 245 | NULL, /* This is a pointer to a GaimPluginUiInfo | |
| 246 | struct. It is a core/ui split way for | |
| 247 | core plugins to have a ui configuration | |
| 248 | frame. You can find an example of this | |
| 249 | code in plugins/pluginpref_example.c | |
| 250 | */ | |
| 251 | NULL /* Finally the last member of the structure, | |
| 252 | is a function pointer where you can define | |
| 253 | menu entries for 'Tools->Plugin Actions'. | |
| 254 | It should be in the form of: | |
| 255 | ||
| 256 | GList *function_name(GaimPlugin *plugin, | |
| 257 | gpointer context) | |
| 258 | ||
| 259 | It should return a GList of | |
| 260 | GaimPluginActions. | |
| 261 | */ | |
| 262 | }; | |
| 263 | @endcode | |
| 264 | ||
| 265 | Finally we have @c init_plugin and @c GAIM_INIT_PLUGIN. @c init_plugin is a | |
| 266 | function that gets called when Gaim probes the plugin. Most plugins will | |
| 267 | add their preferences to the pref tree here, more about that later. | |
|
10469
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
268 | @c GAIM_INIT_PLUGIN is a macro that EVERY plugin MUST have. @c GAIM_INIT_PLUGIN |
|
3edb0348ba88
[gaim-migrate @ 11751]
Mark Doliner <markdoliner@pidgin.im>
parents:
10468
diff
changeset
|
269 | tells Gaim some very basic things about your plugin, like what name to use |
| 10468 | 270 | if the plugin is compiled staticly, the @c init_plugin function, and |
| 271 | the name of the @c GaimPluginInfo structure. As you may have guess this | |
| 272 | also gets read when Gaim is probing your plugin. If this is missing you | |
| 273 | will get the infamous "plugin unloadable for unknown reasons", so do not | |
| 274 | forget it. | |
| 275 | */ |