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