comparison HACKING @ 1237:72692c70317e

[gaim-migrate @ 1247] woo! i have a 10-ish page paper due in 11 hours on a book i haven't read yet. i'm in a writing mood. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Tue, 12 Dec 2000 12:56:53 +0000
parents 4416ead31db7
children ab5dd2c7e7f8
comparison
equal deleted inserted replaced
1236:dcf9242241ee 1237:72692c70317e
1 A lot of people have tried to hack gaim, but haven't been able to because 1 A lot of people have tried to hack gaim, but haven't been able to because
2 the code is just so horrid. Well, the code isn't getting better anytime 2 the code is just so horrid. Well, the code isn't getting better anytime
3 soon, so to help all you would-be hackers help out gaim, here's a brief 3 soon (I hate GNU indent), so to help all you would-be hackers help out
4 tutorial on how gaim works. I'll quickly describe the logical flow of 4 gaim, here's a brief tutorial on how gaim works. I'll quickly describe
5 things, then what you'll find in each of the source files. As an added 5 the logical flow of things, then what you'll find in each of the source
6 bonus, I'll try and describe as best I can how multiple connections and 6 files. As an added bonus, I'll try and describe as best I can how multiple
7 multiple protocols work. Hopefully that's enough to get most of you going. 7 connections and multiple protocols work. Depending on how much I want
8 to avoid my final tomorrow I may even describe other parts of gaim that
9 I particularly want to brag about. Hopefully that's enough to get most
10 of you going.
8 11
9 If you're going to hack gaim, PLEASE, PLEASE PLEASE PLEASE send patches 12 If you're going to hack gaim, PLEASE, PLEASE PLEASE PLEASE send patches
10 against the absolute latest CVS. I get really annoyed when I get patches 13 against the absolute latest CVS. I get really annoyed when I get patches
11 against the last released version, especially since I don't usually have 14 against the last released version, especially since I don't usually
12 a copy of it on my computer, and gaim tends to change a lot between 15 have a copy of it on my computer, and gaim tends to change a lot between
13 versions. (I sometimes get annoyed when they're against CVS from 3 days 16 versions. (I sometimes get annoyed when they're against CVS from 3 days
14 ago, but can't complain because it's usually my fault that I haven't 17 ago, but can't complain because it's usually my fault that I haven't
15 looked at the patch yet.) To get gaim from CVS (if you haven't already), 18 looked at the patch yet.) To get gaim from CVS (if you haven't already),
16 run the following commands: 19 run the following commands:
17 20
18 $ export CVSROOT=:pserver:anonymous@cvs.gaim.sourceforge.net:/cvsroot/gaim 21 $ export CVSROOT=:pserver:anonymous@cvs.gaim.sourceforge.net:/cvsroot/gaim
19 $ cvs login 22 $ cvs login (hit enter as the password)
20 (hit enter as the password)
21 $ cvs co gaim 23 $ cvs co gaim
22 (you'll see it getting all of the files) 24 (you'll see it getting all of the files)
23 $ cd gaim 25 $ cd gaim
24 $ ./gen 26 $ ./gen
25 27
26 You'll now have your normal gaim tree with ./configure and all. (If you 28 You'll now have your normal gaim tree with ./configure and all. (If you
27 want to make your life really simple, learn how CVS works. CVS is your 29 want to make your life really simple, learn how CVS works. CVS is your
28 friend.) 30 friend.) To make a patch, just edit the files right there in that tree
31 (don't bother with two trees, or even two copies of the same file). Then
32 when you're ready to make your patch, simply run 'cvs diff -u >my.patch'
33 and send it off.
29 34
30 There's one little thing that's just a pet peeve, and it's really stupid. 35 There's one little thing that's just a pet peeve, and it's really stupid.
31 In ./configure there's an --enable-debug option. This does two things: 36 In ./configure there's an --enable-debug option. This does two things:
32 compiles with -Wall, and prints debugging information to stdout. The 37 compiles with -Wall, and prints debugging information to stdout. The
33 debugging information is printed to the debug window (which can be turned 38 debugging information is printed to the debug window (which can be turned
34 on in the preferences) whether or not --enable-debug was selected. Most 39 on in the preferences) whether or not --enable-debug was selected. Most
35 of the information that's printed is useless anyway though; so the 40 of the information that's printed is useless anyway though; so the
36 --enable-debug option really doesn't do a whole lot. 41 --enable-debug option really doesn't do a whole lot.
37 42
38 This file was last modified by $Author: warmenhoven $ on $Date: 2000-11-16 02:35:58 -0500 (Thu, 16 Nov 2000) $. 43 This file was last modified by $Author: warmenhoven $ on
44 $Date: 2000-12-12 07:56:53 -0500 (Tue, 12 Dec 2000) $.
39 45
40 46
41 PROGRAM FLOW 47 PROGRAM FLOW
42 ============ 48 ============
43 49
45 mostly just reading .gaimrc (handled by the functions in gaimrc.c) and 51 mostly just reading .gaimrc (handled by the functions in gaimrc.c) and
46 parsing command-line options. It then draws the login window by calling 52 parsing command-line options. It then draws the login window by calling
47 show_login, and waits for input. 53 show_login, and waits for input.
48 54
49 At the login window, when "Accounts" is clicked, account_editor() is 55 At the login window, when "Accounts" is clicked, account_editor() is
50 called. This then displays all of the users and various information about 56 called. This then displays all of the users and various information
51 them. If the user clicks the "Signon" button instead, serv_login is called. 57 about them. If the user clicks the "Signon" button instead, serv_login
58 is called.
52 59
53 When the "Sign on/off" button is clicked, serv_login is passed the 60 When the "Sign on/off" button is clicked, serv_login is passed the
54 username and the password for the account. If the password length is 61 username and the password for the account. If the password length is
55 zero (the password field is a character array rather than pointer so 62 zero (the password field is a character array rather than pointer so it
56 it will not be NULL) then the Signon callback will prompt for the 63 will not be NULL) then the Signon callback will prompt for the password
57 password before calling serv_login. serv_login then signs in the user 64 before calling serv_login. serv_login then signs in the user using the
58 using the appropriate protocol. We'll assume TOC for the rest of this 65 appropriate protocol. We'll assume TOC for the rest of this discussion;
59 discussion; Oscar has a lot of bad hacks to get it working that I don't 66 even the libfaim guys get scared by oscar.c, and I'll talk about the
60 even want to think about. 67 PRPLs later.
61 68
62 After you're signed in (I'll skip that discussion - I doubt many people 69 After you're signed in (I'll skip that discussion - I doubt many people
63 are going to change the login process, since it pretty much just follows 70 are going to change the login process, since it pretty much just follows
64 PROTOCOL), Gaim draws the buddy list by calling show_buddy_list, and 71 PROTOCOL), Gaim draws the buddy list by calling show_buddy_list, and
65 waits for input from two places: the server and the user. The first place 72 waits for input from two places: the server and the user. The first
66 it gets input from after signon is usually the server, when the server 73 place it gets input from after signon is usually the server, when the
67 tells Gaim which buddies are signed on. 74 server tells Gaim which buddies are signed on.
68 75
69 When there is information ready to be read from the server, toc_callback 76 When there is information ready to be read from the server, toc_callback
70 is called (by GDK) to parse the incoming information. On an UPDATE, 77 is called (by GDK) to parse the incoming information. On an UPDATE,
71 serv_got_update is called, which takes care of things like notifying 78 serv_got_update is called, which takes care of things like notifying
72 conversation windows of the update if need be; notifying the plugins; 79 conversation windows of the update if need be; notifying the plugins;
73 and finally, calling set_buddy. 80 and finally, calling set_buddy.
74 81
75 New connections happen the exact same way as described above. Each aim_user 82 set_buddy is responsible for a lot of stuff, but most of it is done
76 can have one gaim_connection associated with it. aim_user and gaim_connection 83 implicitly. It's responsible for the sounds (which is just a call to
77 both have a protocol field; gaim_connection's should be constant once it is 84 play_sound), but the biggest thing it does is call new_group_show and
78 set in the appropriate (protocol)_login function. There are lots of details 85 new_buddy_show if necessary. There's only one group_show per group name,
79 that are connected with multiple connections that are best explained by 86 even between connections, and only one buddy_show per group_show per
80 reading the code. 87 buddy name, even between connections. (If that's not confusing enough,
88 wait until I really start describing how the buddy list works.)
89
90 New connections happen the exact same way as described above. Each
91 aim_user can have one gaim_connection associated with it. aim_user and
92 gaim_connection both have a protocol field; gaim_connection's should
93 be constant once it is set. (I'll talk about the gaim_connection struct
94 more later.)
81 95
82 When the user opens a new conversation window, new_conversation is called. 96 When the user opens a new conversation window, new_conversation is called.
83 That's easy enough. If there isn't a conversation with the person already 97 That's easy enough. If there isn't a conversation with the person already
84 open (checked by calling find_conversation), show_conv is called to 98 open (checked by calling find_conversation), show_conv is called to
85 create the new window. All sorts of neat things happen there, but it's 99 create the new window. All sorts of neat things happen there, but it's
97 Not much to say here, just a few basic functions. 111 Not much to say here, just a few basic functions.
98 112
99 aim.c: 113 aim.c:
100 This is where the main() function is. It takes care of a lot of the 114 This is where the main() function is. It takes care of a lot of the
101 initialization stuff, and showing the login window. It's pretty tiny 115 initialization stuff, and showing the login window. It's pretty tiny
102 and there's not really much to edit in it. Watch out for bad Oscar 116 and there's not really much to edit in it. This has some of the most
103 sign in hacks. 117 pointless functions, like gaim_setup, which optionally turns off sounds
118 on signon. A lot of this file should actually be part of other files.
104 119
105 away.c: 120 away.c:
106 This takes care of most of the away stuff: setting the away message 121 This takes care of most of the away stuff: setting the away message
107 (do_im_away); coming back (do_im_back); drawing the away window; 122 (do_away_message); coming back (do_im_back); drawing the away window;
108 etc. To be honest I haven't looked at this file in months. 123 etc.
109 124
110 browser.c: 125 browser.c:
111 Code for opening a browser window. Most of the code is trying to deal 126 Code for opening a browser window. Most of the code is trying to deal
112 with Netscape. The most important function here is open_url. Have fun. 127 with Netscape. The most important function here is open_url. Have fun.
128 (This file may give you problems with GTK 2.0, because it uses parts
129 of GDK that it's not supposed to know about.)
113 130
114 buddy.c: 131 buddy.c:
115 This takes care of not only nearly everything buddy-related (the buddy 132 This takes care of not only nearly everything buddy-related (the
116 list, the permit/deny lists, and the window), but also a lot of the 133 buddy lists, the window, etc.), but also a lot of the code flow and
117 code flow and util functions. Look for good things like find_buddy, 134 util functions. Look for good things like find_buddy, set_buddy,
118 set_buddy, and signoff() here. 135 and signoff here.
119 136
120 buddy_chat.c: 137 buddy_chat.c:
121 This takes care of the buddy chat stuff. This used to be a lot bigger 138 This takes care of the buddy chat stuff. This used to be a lot bigger
122 until the chat and IM windows got merged in the code. Now it mostly 139 until the chat and IM windows got merged in the code. Now it mostly
123 just takes care of chat-specific stuff, like ignoring people and 140 just takes care of chat-specific stuff, like ignoring people and
127 conversation.c: 144 conversation.c:
128 This is where most of the functions dealing with the IM and chat windows 145 This is where most of the functions dealing with the IM and chat windows
129 are hidden. It tries to abstract things as much as possible, but doesn't 146 are hidden. It tries to abstract things as much as possible, but doesn't
130 do a very good job. This is also where things like "Enter sends" and 147 do a very good job. This is also where things like "Enter sends" and
131 "Ctrl-{B/I/U/S}" options get carried out (look for send_callback). The 148 "Ctrl-{B/I/U/S}" options get carried out (look for send_callback). The
132 chat and IM toolbar (with the B/I/U/S buttons) are both built from the 149 chat and IM toolbar (with the B/I/U/S buttons) are both built from
133 same function, build_conv_toolbar. 150 the same function, build_conv_toolbar.
134 151
135 dialogs.c: 152 dialogs.c:
136 A massive file with a lot of little utility functions. This is where 153 A massive file with a lot of little utility functions. This is where all
137 all of those little dialog windows are created. Things like the warn 154 of those little dialog windows are created. Things like the warn dialog
138 dialog and the add buddy dialog are here. Not all of the dialogs in 155 and the add buddy dialog are here. Not all of the dialogs in gaim are in
139 gaim are in this file, though. But most of them are. This is also 156 this file, though. But most of them are. This is also where do_import
140 where do_import is housed, to import buddy lists. 157 is housed, to import buddy lists. (The actual buddy list parsing code
158 is in util.c for winaim lists and toc.c for gaim's own lists.)
141 159
142 gaimrc.c: 160 gaimrc.c:
143 This controls everything about the .gaimrc file. There's not really much 161 This controls everything about the .gaimrc file. There's not really much
144 to say about it; this is probably one of the better designed and easier 162 to say about it; this is probably one of the better designed and easier
145 to follow files in gaim. The important functions are towards the bottom. 163 to follow files in gaim. The important functions are towards the bottom.
146 164
147 gnome_applet_mgr.c: 165 gnome_applet_mgr.c:
148 A hideous creation from the days before I started working on gaim. Most 166 This controls most things that are related to the applet. I don't like
149 of it works, but it has functionsLikeThis. I hate looking at this 167 looking at this file because it still has functionsLikeThis. But at
150 file, but I'm too lazy to change the functions. The best functions 168 least it doesn't have many of them anymore. Anyway, this file isn't
151 are things like set_applet_draw_open, whose sole purpose is to set a 169 very big because there's really not much difference between the panel
152 global variable to TRUE. [ note 8/22/00 - I finally changed this file. ] 170 version and the app version.
153 171
154 gtkhtml.c: 172 gtkhtml.c:
155 This is really just one big hack. It started off as an HTML widget that 173 This is really just one big hack. I recommend not looking at this
156 was written for Gnome as far as I can tell. The current version is 174 file if you want to save your sanity. (It's going to be replaced
157 huge, requires way too many libs, and is too hard to upgrade to. But 175 eventually anyway.) People have asked why we don't replace this with
158 we've managed to hack this poor old version into basically what we 176 GNOME's GtkHTML, or embed mozilla (yes, they were serious). There
159 need it for. I recommend not looking at this file if you want to save 177 are two reasons. The first is that doing that would cause gaim to
160 your sanity. 178 require 6 extra libraries that nobody needs or wants or has. The
179 second is that we really don't need, or even want, a full-fledged
180 HTML viewer. We don't even want a normal HTML viewer because the text
181 that gets sent gets parsed and displayed different than normal HTML.
182 (Try inserting a newline and you'll see what I mean.) We should only
183 support about 12 tags, not the 50 that normal HTML supports.
161 184
162 gtkticker.c: 185 gtkticker.c:
163 Syd, our resident GTK God, wrote a GtkWidget, GtkTicker. This is that 186 Syd, our resident GTK God, wrote a GtkWidget, GtkTicker. This is that
164 widget. It's cool, and it's tiny. 187 widget. It's cool, and it's tiny.
165 188
170 193
171 idle.c: 194 idle.c:
172 This file used to be entirely #if 0'd out of existance. However, thanks 195 This file used to be entirely #if 0'd out of existance. However, thanks
173 to some very generous people who submitted patches, this takes care of 196 to some very generous people who submitted patches, this takes care of
174 reporting idle time (imagine that). It's a pretty straight-forward file. 197 reporting idle time (imagine that). It's a pretty straight-forward file.
198 This also takes care of the auto-away stuff.
175 199
176 multi.c: 200 multi.c:
177 This is the file that tries to take care of most of the major issues 201 This is the file that tries to take care of most of the major issues
178 with multiple connections. The best function in here by far is the 202 with multiple connections. The best function in here by far is the
179 account_editor(). auto_login() is also in here (I'm just reading 203 account_editor(). auto_login() is also in here (I'm just reading multi.h
180 multi.h now...); auto_login has problems. Someone please fix it. 204 now...). account_editor is really the only function that the UI needs
181 account_editor is really the only function that the UI needs to be 205 to be concerned with.
182 concerned with. If you want to remove multiconnectivity from gaim,
183 all you would really need to do is comment out any lines that make
184 reference to this function (there are only two - one in aim.c and one
185 in buddy.c). Or you could just run ./configure --disable-multi.
186 206
187 oscar.c: 207 oscar.c:
188 One big hack of copied code. This is supposed to be the libfaim tie-in 208 One big hack of copied code. This is supposed to be the libfaim tie-in
189 in gaim. Most of it is just copied straight from faimtest, the small 209 in gaim. Most of it is just copied straight from faimtest, the small
190 program that comes with libfaim. I'm not even sure how half of it works, 210 program that comes with libfaim. I'm not even sure how half of it works,
209 The important function in here is build_prefs, but the most useful 229 The important function in here is build_prefs, but the most useful
210 function is gaim_button. build_prefs draws the window, and calls 230 function is gaim_button. build_prefs draws the window, and calls
211 gaim_button probably 30 or 40 times. (I don't really wanna run grep 231 gaim_button probably 30 or 40 times. (I don't really wanna run grep
212 | wc to count.) This is where you add the toggle button for gaim 232 | wc to count.) This is where you add the toggle button for gaim
213 preferences. It's very simple, and if you look at a couple of the 233 preferences. It's very simple, and if you look at a couple of the
214 calls to gaim_button you'll figure it out right away. 234 calls to gaim_button you'll figure it out right away. The new prefs
235 window uses a CList instead of a Notebook, and there's a pretty bad
236 hack to get it to work. I won't tell you what though.
215 237
216 prpl.c: 238 prpl.c:
217 This file is what lets gaim dynamically load protocols, sort of. All of 239 This file is what lets gaim dynamically load protocols, sort of. All
218 the actual dlopen(), dlsym() stuff is in plugins.c. But this contains 240 of the actual dlopen(), dlsym() stuff is in plugins.c. But this
219 all of the functions that the protocol plugin needs to call, and manages 241 contains all of the functions that the protocol plugin needs to call,
220 all of the protocols. It's a pretty simple file actually. 242 and manages all of the protocols. It's a pretty simple file actually.
221 243
222 proxy.c: 244 proxy.c:
223 Adam (of libfaim glory) got bored one day and rewrote this file, so now 245 Adam (of libfaim glory) got bored one day and rewrote this file, so
224 everything actually works. The main function is proxy_connect, which 246 now everything actually works. The main function is proxy_connect,
225 figures out which proxy you want to use (if you want to use one at all) 247 which figures out which proxy you want to use (if you want to use one
226 and passes off the data to the appropriate function. This file should be 248 at all) and passes off the data to the appropriate function. This file
227 pretty straight-forward. 249 should be pretty straight-forward.
228 250
229 rvous.c: 251 rvous.c:
230 This was originally going to be the stuff for all of the Buddy Icon 252 This was originally going to be the stuff for all of the Buddy Icon
231 and Voice Chat stuff, but I got really sick of protocol hacking really 253 and Voice Chat stuff, but I got really sick of protocol hacking really
232 quick. Now it only houses the file transfer stuff, which only works 254 quick. Now it only houses the file transfer stuff, which only works
233 for TOC. 255 for TOC. ("Works" being a very subjective statement. This file needs
256 to be rewritten.)
234 257
235 server.c: 258 server.c:
236 This is where all of the differentiation between TOC and Oscar is 259 This is where all of the differentiation between the different protocols
237 done. Nearly everything that's network related goes through here 260 is done. Nearly everything that's network related goes through here
238 at one point or another. This has good things like serv_send_im and 261 at one point or another. This has good things like serv_send_im and
239 serv_got_update. Most of it should be pretty self-explanatory. 262 serv_got_update. Most of it should be pretty self-explanatory.
240 263
241 sound.c: 264 sound.c:
242 The main function in this file is play_sound, which plays one of 8 265 The main function in this file is play_sound, which plays one of 8
243 (maybe 9?) sounds based on preferences. All that the rest of the 266 (maybe 9?) sounds based on preferences. All that the rest of the code
244 code should have to do is call play_sound(BUDDY_ARRIVE), for example, 267 should have to do is call play_sound(BUDDY_ARRIVE), for example, and
245 and this file will take care of determining if a sound should be played 268 this file will take care of determining if a sound should be played
246 and which file should be played. 269 and which file should be played.
247 270
248 ticker.c: 271 ticker.c:
249 Syd is just so cool. I really can't get over it. He let me come 272 Syd is just so cool. I really can't get over it. He let me come
250 visit him at Netscape one day, and I got to see all of their toys 273 visit him at Netscape one day, and I got to see all of their toys
254 as cool as Syd. 277 as cool as Syd.
255 278
256 toc.c: 279 toc.c:
257 This handles everything TOC-related, including parsing gaim's buddy 280 This handles everything TOC-related, including parsing gaim's buddy
258 list. Most of this file is toc_callback, which parses the incoming 281 list. Most of this file is toc_callback, which parses the incoming
259 information from the server. I really don't like TOC though. 282 information from the server. I really don't like TOC though. (I've spent
283 waaayyyy too much time with TOC. I rewrote the signon process for this
284 file at one point, so that read was only called when data was pending.
285 Since then the TOC server has been blocking my IP (probably my own
286 stupid fault, sending bad strings or some such).)
260 287
261 util.c: 288 util.c:
262 There's not really a lot of cohesion to this file; it's just a lot of 289 There's not really a lot of cohesion to this file; it's just a lot of
263 stuff that happened to be thrown into it for no apparent reason. None 290 stuff that happened to be thrown into it for no apparent reason. None
264 of it is particularly tasty; it's all just utility functions. Just 291 of it is particularly tasty; it's all just utility functions. Just
265 like the name says. 292 like the name says.
266 293
267 294
295 HOW THE BUDDY LIST WORKS
296 ========================
297
298 The buddy list is a pain in the ass. Let me start off by saying that. The
299 most difficult part about getting gaim to do multiple connections was
300 the buddy list. In its current state it's very much like the UI for
301 0.10.x and earlier, which is what I was aiming for. However, the code
302 is completely different. And not much better.
303
304 All of the buddy list stuff is in buddy.c, so you'll only have to have
305 that one file open (and possibly gaim.h for the struct definitions). There
306 are two sets of functions: those that deal with the buddy lists, and
307 those that deal with the window. (I say lists because each connection
308 has their own buddy list, independent of the others, even though the UI
309 merges them.)
310
311 The buddy list functions work pretty much the same way they did before;
312 except now that each buddy and group belongs to a connection, things
313 like find_buddy take an additional argument, the connection you want to
314 search for the buddy in. Read gaim.h for a good list of them: find_buddy,
315 find_group, add_buddy, remove_buddy, remove_group.
316
317 The window is a lot more fun. There's really only one function that
318 does anything interesting, and that's set_buddy. (There's also things
319 like build_edit_tree, but that's boring.) set_buddy is called by
320 serv_got_update (and should only be called by that function) any time
321 a user signs on, signs off, goes away, comes back, goes idle, etc, etc,
322 etc. Various things happen depending on the new state of the buddy.
323
324 struct buddy has a member, present, which is set to either 0, 1, or
325 2. You can check if the buddy is online with "if (b->present)". This
326 becomes important. present is set to either 0 or 1 by serv_got_update,
327 or is not set at all. When the buddy is passed to set_buddy, if present
328 is 1 then set_buddy plays the BUDDY_ARRIVE sound, and sets present to 2,
329 to indicate it has already received notification of arrival. It then
330 does other signin-related stuff: setting the pixmap to the login icon;
331 updating the conversation windows; etc.
332
333 The most important thing it does though, if a buddy is present, is it
334 checks for the existance of the appropriate group_show and buddy_show for
335 that buddy. Each buddy must belong to a group. group_shows are based on
336 name; there can only be one group_show for each group name. buddy_shows
337 are based both on name and on group_show; there can only be one buddy_show
338 in a group_show for each name. However, there can be two buddy_shows
339 with the same name as long as they have different group_shows.
340
341 Each buddy_show has a GList of connections that has registered its related
342 buddy as being online. set_buddy makes sure that the connection that it's
343 being passed is part of the connlist for the buddy_show associated with
344 the struct buddy that it's passed (it helps to know your data structures).
345
346 If a buddy logs off (b->present == 0), and a buddy_show exists for
347 that buddy, then set_buddy will play the logoff sound, change the icon,
348 remove the connection from the connlist for the buddy_show, etc.
349
350 And that's how that works. For the buddy lists, connections own buddies;
351 for the window, the buddies own the connections. When the buddy_show
352 connlist count drops to zero it disappears from existance.
353
354
355 PLUGINS
356 =======
357
358 OK, so you want to load a plugin. You go through whatever UI (you
359 can read all about the UI in plugins.c or whereever). You finally get
360 to load_plugin, the meat of the plugins stuff (plugins can actually
361 call load_plugin themselves to load other plugins). load_plugin
362 is passed the full path to the plugin you want to load
363 (e.g. /usr/local/lib/gaim/irc.so).
364
365 load_plugin does a few things with that filename. The first is to see
366 if you've already loaded that plugin. If you have, load_plugin unloads
367 the one that is currently loaded. You might wonder why; it's because
368 the same plugin can't be loaded twice. If you call g_module_open on a
369 filename twice, both times it will return the same pointer, and both times
370 increment the reference count on the GModule * that it returns. This
371 means you really do have the same plugin twice, which fucks up the
372 callback system to no end. So it's better that you can only have it
373 loaded once at any given time.
374
375 Now that we're assured that we don't have this particular plugin loaded
376 yet, we better load it. g_module_open, baby. Much more portable than
377 dlopen(). In fact, for Linux it actually is the equivalent of dlopen()
378 (you can read the gmodule source and see for yourself). There's only one
379 quirk. It always logically ORs the options you pass with RTLD_GLOBAL,
380 which means that plugins share symbols. I haven't figured out yet if
381 this means just functions or variables too; but in either case make every
382 function and variable in your plugin static except for gaim_plugin_*(),
383 name(), and description(). It's good coding practice anyway.
384
385 So, assuming we didn't get NULL back from g_module_open, we then make sure
386 it's a valid gaim plugin by looking for and calling gaim_plugin_init,
387 courtesy g_module_symbol (g_module_symbol is actually what's portable
388 about gmodule as opposed to dl*; some BSD's require '_' prepended to
389 symbol names and g_module_symbol guarantees we do The Right Thing).
390
391 Assuming we've found gaim_plugin_init and it hasn't returned non-NULL
392 to us, we then add it to our list of plugins and go merrily about our way.
393
394 So when do the callbacks happen?! plugin_event, baby, plugin_event. Any
395 time you want to trigger a plugin event simply call plugin_even with the
396 parameters to be passed to any event handlers and you're set. plugin_event
397 then makes sure that any plugins waiting for the event get passed the
398 arguments properly and passes it on to perl.
399
400 Speaking of perl. If you really want to know how this works, you're
401 better off reading X-Chat's documentation of it, because it's better
402 than what I could provide.
403
404
268 MULTIPLE CONNECTIONS AND PRPLS 405 MULTIPLE CONNECTIONS AND PRPLS
269 ============================== 406 ==============================
270 407
271 OK, let's start with the basics. There are users. Each user is contained 408 OK, let's start with the basics. There are users. Each user is contained
272 in an aim_user struct, and kept track of in the aim_users GList (GSList?). 409 in an aim_user struct, and kept track of in the aim_users GList (GSList?).
273 Each aim_user has certain features: a username, a password, and user_info. 410 Each aim_user has certain features: a username, a password, and user_info.
274 It also has certain options, and the protocol it uses to sign on (kept as 411 It also has certain options, and the protocol it uses to sign on (kept
275 an int which is #define'd in prpl.h). The way the management of the users 412 as an int which is #define'd in prpl.h). The way the management of the
276 works is, there will (hopefully) only be one user for a given screenname/ 413 users works is, there will (hopefully) only be one user for a given
277 protocol pair (i.e. you may have two user warmenhoven's, but they'll both 414 screenname/ protocol pair (i.e. you may have two user warmenhoven's,
278 have a different protocol number). 415 but they'll both have a different protocol number).
279 416
280 Now then, there are protocols that gaim knows about. Each protocol is in 417 Now then, there are protocols that gaim knows about. Each protocol is
281 a prpl struct and kept track of in the protocols GSList. The way the 418 in a prpl struct and kept track of in the protocols GSList. The way the
282 management of the protocols is, there will only ever be one prpl per numeric 419 management of the protocols is, there will only ever be one prpl per
283 protocol. Each prpl defines a basic set of functions: login, logout, send_im, 420 numeric protocol. Each prpl defines a basic set of functions: login,
284 etc. The prpl is responsible not only for handling these functions, but also 421 logout, send_im, etc. The prpl is responsible not only for handling
285 for calling the appropriate serv_got functions (e.g. serv_got_update when a 422 these functions, but also for calling the appropriate serv_got functions
286 buddy comes online/goes offline/goes idle/etc). It handles each of these on 423 (e.g. serv_got_update when a buddy comes online/goes offline/goes
287 a per-connection basis. 424 idle/etc). It handles each of these on a per-connection basis.
288 425
289 So why's it called a PRPL? It stands for PRotocol PLugin. That means that 426 So why's it called a PRPL? It stands for PRotocol PLugin. That means
290 it's possible to dynamically add new protocols to gaim. However, all protocols 427 that it's possible to dynamically add new protocols to gaim. However,
291 must be implemented the same way: by using a prpl struct and being loaded, 428 all protocols must be implemented the same way: by using a prpl struct
292 regardless of whether they are static or dynamic. 429 and being loaded, regardless of whether they are static or dynamic.
293 430
294 Here's how struct gaim_connection fits into all of this. At some point the 431 Here's how struct gaim_connection fits into all of this. At some point
295 User (capitalized to indicate a person and not a name) will try to sign on 432 the User (capitalized to indicate a person and not a name) will try to
296 one of Their users. serv_login is then called for that user. It searches for 433 sign on one of Their users. serv_login is then called for that user. It
297 the prpl that is assigned to that user, and calls that prpl's login function, 434 searches for the prpl that is assigned to that user, and calls that prpl's
298 passing it the aim_user struct that is attempting to sign on. The prpl is then 435 login function, passing it the aim_user struct that is attempting to sign
299 responsible for seeing that the gaim_connection is created (by calling 436 on. The prpl is then responsible for seeing that the gaim_connection
300 new_gaim_connection), and registering it as being online (by calling 437 is created (by calling new_gaim_connection), and registering it as
301 account_online and passing it the aim_user and gaim_connection structs). At 438 being online (by calling account_online and passing it the aim_user and
302 that point, the aim_user and gaim_connection structs have pointers to each 439 gaim_connection structs). At that point, the aim_user and gaim_connection
303 other, and the gaim_connection struct has a pointer to the prpl struct that 440 structs have pointers to each other, and the gaim_connection struct has
304 it is using. The gaim_connections are stored in the connections GSList. 441 a pointer to the prpl struct that it is using. The gaim_connections are
305 The way connection management works is, there will always only be one 442 stored in the connections GSList. The way connection management works is,
306 gaim_connection per user, and the prpl that the gaim_connection uses will be 443 there will always only be one gaim_connection per user, and the prpl that
307 constant for the gaim_connection's life. 444 the gaim_connection uses will be constant for the gaim_connection's life.
308 445
309 So at certain points the User is going to want to do certain things, like 446 So at certain points the User is going to want to do certain things,
310 send a message. They must send the message on a connection. So the UI figures 447 like send a message. They must send the message on a connection. So the UI
311 out which gaim_connection the User want to send a message on (for our example), 448 figures out which gaim_connection the User want to send a message on (for
312 and calls serv_send_im, telling it which gaim_connection to use, and the 449 our example), and calls serv_send_im, telling it which gaim_connection to
313 necessary information (who to send it to, etc). The serv_ function then 450 use, and the necessary information (who to send it to, etc). The serv_
314 calls the handler of the prpl of the connection for that event (that was way 451 function then calls the handler of the prpl of the connection for that
315 too many prepositions). OK, each prpl has a send_im function. Each connection 452 event (that was way too many prepositions). OK, each prpl has a send_im
316 has a prpl. so you call gc->prpl->send_im and pass it the connection and all 453 function. Each connection has a prpl. so you call gc->prpl->send_im and
317 the necessary info. And that's how things get done. 454 pass it the connection and all the necessary info. And that's how things
455 get done.
318 456
319 I hope some of that made sense. Looking back at it it makes absolutely no 457 I hope some of that made sense. Looking back at it it makes absolutely no
320 sense to me. Thank god I wrote the code; otherwise I'm sure I'd be lost. 458 sense to me. Thank god I wrote the code; otherwise I'm sure I'd be lost.