11218
|
1 #include <stdio.h>
|
|
2 #include <assert.h>
|
|
3 #include <internal.h>
|
|
4 #include <plugin.h>
|
|
5 #include <gtkplugin.h>
|
|
6 #include <gtkblist.h>
|
|
7 #include <gtkutils.h>
|
|
8 #include <connection.h>
|
|
9 #include <conversation.h>
|
|
10 #include <network.h>
|
|
11 #include <gtk/gtkgl.h>
|
|
12 #include <GL/gl.h>
|
|
13 #include <GL/glu.h>
|
|
14 #include "crazychat.h"
|
|
15 #include "cc_network.h"
|
|
16 #include "cc_interface.h"
|
|
17 #include "cc_gtk_gl.h"
|
|
18 #include "util.h"
|
|
19
|
|
20 /* --- begin type and global variable definitions --- */
|
|
21
|
|
22 static struct crazychat cc_info;
|
|
23
|
|
24 /* --- begin function declarations --- */
|
|
25
|
|
26 /**
|
|
27 * Called by gaim plugin to start CrazyChat
|
|
28 * @param cc the crazychat struct
|
|
29 */
|
|
30 static void cc_init(struct crazychat *cc);
|
|
31
|
|
32 /**
|
|
33 * Called by gaim plugin to destroy CrazyChat
|
|
34 * @param cc the crazychat struct
|
|
35 */
|
|
36 static void cc_destroy(struct crazychat *cc);
|
|
37
|
|
38
|
|
39 /**
|
|
40 * Buddy menu drawing callback. Adds a CrazyChat menuitem.
|
|
41 * @param menu the buddy menu widget
|
|
42 * @param b the buddy whose menu this is
|
|
43 */
|
|
44 static gboolean cc_buddy_menu(GtkWidget *menu, GaimBuddy *b);
|
|
45
|
|
46 /**
|
|
47 * Buddy menu callback. Initiates the CrazyChat session.
|
|
48 * @param item the gtk buddy menu item
|
|
49 * @param b the buddy whose menu the item was in
|
|
50 */
|
|
51 static void cc_menu_cb(GtkMenuItem *item, GaimBuddy *b);
|
|
52
|
|
53 /**
|
|
54 * IM callback. Handles receiving a CrazyChat session request.
|
|
55 * @param account the account we received the IM on
|
|
56 * @param sender the buddy who we received the message from
|
|
57 * @param message the message we received
|
|
58 * @param flags IM flags
|
|
59 * @param data user data
|
|
60 */
|
|
61 static gboolean receive_im_cb(GaimAccount *account, char **sender,
|
|
62 char **message, int *flags, void *data);
|
|
63
|
|
64 /**
|
|
65 * Displaying IM callback. Drops CrazyChat messages from IM window.
|
|
66 * @param account the account we are displaying the IM on
|
|
67 * @param conv the conversation we are displaying the IM on
|
|
68 * @param message the message we are displaying
|
|
69 * @param data user data
|
|
70 */
|
|
71 static gboolean display_im_cb(GaimAccount *account, GaimConversation *conv,
|
|
72 char **message, void *data);
|
|
73
|
|
74 /**
|
|
75 * Callback for CrazyChat plugin configuration frame
|
|
76 * @param plugin the plugin data
|
|
77 * @return the configuration frame
|
|
78 */
|
|
79 static GtkWidget *get_config_frame(GaimPlugin *plugin);
|
|
80
|
|
81 /**
|
|
82 * TCP port callback. Changes the port used to listen for new CC sessions
|
|
83 * @param spin the spinner button whose value changed
|
|
84 * @param data user data
|
|
85 */
|
|
86 static void tcp_port_cb(GtkSpinButton *spin, struct crazychat *cc);
|
|
87
|
|
88 /**
|
|
89 * UDP port callback. Changes the port used to send/recv CC session frames
|
|
90 * @param spin the spinner button whose value changed
|
|
91 * @param data user data
|
|
92 */
|
|
93 static void udp_port_cb(GtkSpinButton *spin, struct crazychat *cc);
|
|
94
|
|
95 /**
|
|
96 * Features enabling/disabling callback. Initializes the input processing
|
|
97 * or shuts it down.
|
|
98 * @param data user data
|
|
99 */
|
|
100 static void features_enable_cb(struct crazychat *cc);
|
|
101
|
|
102 /**
|
|
103 * User signed on callback. Now we have a buddy list to connect a signal
|
|
104 * handler to.
|
|
105 * @param gc the gaim connection we are signed on
|
|
106 * @param plugin our plugin struct
|
|
107 */
|
|
108 static gboolean cc_signed_on(GaimConnection *gc, void *plugin);
|
|
109
|
|
110 /**
|
|
111 * Plugin loading callback. If a buddy list exists, connect our buddy menu
|
|
112 * drawing callback to the signal handler, otherwise, connect a signed on
|
|
113 * signal handler so we know when we get a buddy list.
|
|
114 * @param plugin our plugin struct
|
|
115 */
|
|
116 static gboolean plugin_load(GaimPlugin *plugin);
|
|
117
|
|
118 /**
|
|
119 * Plugin unloading callback. Disconnect all handlers and free data.
|
|
120 * @param plugin our plugin struct
|
|
121 */
|
|
122 static gboolean plugin_unload(GaimPlugin *plugin);
|
|
123
|
|
124
|
|
125 /* --- end function declarations --- */
|
|
126
|
|
127
|
|
128 #define CRAZYCHAT_PLUGIN_ID "gtk-crazychat"
|
|
129
|
|
130 static GaimGtkPluginUiInfo ui_info = {
|
|
131 get_config_frame /**< get_config_frame */
|
|
132 };
|
|
133
|
|
134 static GaimPluginInfo info = {
|
|
135 2, /**< api_version */
|
|
136 GAIM_PLUGIN_STANDARD, /**< type */
|
|
137 GAIM_GTK_PLUGIN_TYPE, /**< ui_requirement */
|
|
138 0, /**< flags */
|
|
139 NULL, /**< dependencies */
|
|
140 GAIM_PRIORITY_DEFAULT, /**< priority */
|
|
141
|
|
142 CRAZYCHAT_PLUGIN_ID, /**< id */
|
|
143 N_("Crazychat"), /**< name */
|
|
144 VERSION, /**< version */
|
|
145 /** summary */
|
|
146 N_("Plugin to establish a Crazychat session."),
|
|
147 /** description */
|
|
148 N_("Uses Gaim to obtain buddy ips to connect for a Crazychat session"),
|
|
149 "\n"
|
|
150 "William Chan <chanman@stanford.edu>\n"
|
|
151 "Ian Spiro <ispiro@stanford.edu>\n"
|
|
152 "Charlie Stockman<stockman@stanford.edu>\n"
|
|
153 "Steve Yelderman<scy@stanford.edu>", /**< author */
|
|
154 GAIM_WEBSITE, /**< homepage */
|
|
155
|
|
156 plugin_load, /**< load */
|
|
157 plugin_unload, /**< unload */
|
|
158 NULL, /**< destroy */
|
|
159
|
|
160 &ui_info, /**< ui_info */
|
|
161 &cc_info /**< extra_info */
|
|
162 };
|
|
163
|
|
164 /* --- end plugin struct definition --- */
|
|
165
|
|
166 static void cc_init(struct crazychat *cc)
|
|
167 {
|
|
168 /* initialize main crazychat thread */
|
|
169
|
|
170 assert(cc);
|
|
171 memset(cc, 0, sizeof(*cc));
|
|
172
|
|
173 /* initialize network configuration */
|
|
174 cc->tcp_port = DEFAULT_CC_PORT;
|
|
175 cc->udp_port = DEFAULT_CC_PORT;
|
|
176
|
|
177 /* disable input subsystem */
|
|
178 //cc->features_state = 0;
|
|
179
|
|
180 /* initialize input subsystem */
|
|
181 cc->features_state = 1;
|
|
182 cc->input_data = init_input(cc);
|
|
183 }
|
|
184
|
|
185 static void cc_destroy(struct crazychat *cc)
|
|
186 {
|
|
187 assert(cc);
|
|
188
|
|
189 if (cc->features_state) {
|
|
190 destroy_input(cc->input_data);
|
|
191 }
|
|
192 memset(cc, 0, sizeof(*cc));
|
|
193 }
|
|
194
|
|
195 static gboolean cc_buddy_menu(GtkWidget *menu, GaimBuddy *b)
|
|
196 {
|
|
197 GtkWidget *menuitem;
|
|
198
|
|
199 menuitem = gtk_menu_item_new_with_mnemonic("CrazyChat");
|
|
200 g_signal_connect(G_OBJECT(menuitem), "activate",
|
|
201 G_CALLBACK(cc_menu_cb), b);
|
|
202 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
|
|
203 return FALSE;
|
|
204 }
|
|
205
|
|
206 static void cc_menu_cb(GtkMenuItem *item, GaimBuddy *b)
|
|
207 {
|
|
208 assert(item);
|
|
209 assert(b);
|
|
210
|
|
211 /* send the invite */
|
|
212 cc_net_send_invite(&cc_info, b->name, b->account);
|
|
213 }
|
|
214
|
|
215 static gboolean receive_im_cb(GaimAccount *account, char **sender,
|
|
216 char **message, int *flags, void *data)
|
|
217 {
|
|
218 struct crazychat *cc;
|
|
219
|
|
220 cc = (struct crazychat*)data;
|
|
221 assert(cc);
|
|
222 if (!strncmp(*message, CRAZYCHAT_INVITE_CODE,
|
|
223 strlen(CRAZYCHAT_INVITE_CODE))) {
|
|
224 Debug(*message);
|
|
225 char *split = strchr(*message, '!');
|
|
226 assert(split);
|
|
227 *split = 0;
|
|
228 split++;
|
|
229 cc_net_recv_invite(account, cc, *sender,
|
|
230 &(*message)[strlen(CRAZYCHAT_INVITE_CODE)],
|
|
231 split);
|
|
232 return TRUE;
|
|
233 } else if (!strncmp(*message, CRAZYCHAT_ACCEPT_CODE,
|
|
234 strlen(CRAZYCHAT_ACCEPT_CODE))) {
|
|
235 cc_net_recv_accept(account, cc, *sender,
|
|
236 &(*message)[strlen(CRAZYCHAT_ACCEPT_CODE)]);
|
|
237 return TRUE;
|
|
238 } else if (!strncmp(*message, CRAZYCHAT_READY_CODE,
|
|
239 strlen(CRAZYCHAT_READY_CODE))) {
|
|
240 cc_net_recv_ready(account, cc, *sender);
|
|
241 return TRUE;
|
|
242 }
|
|
243
|
|
244 return FALSE;
|
|
245 }
|
|
246
|
|
247 static gboolean display_im_cb(GaimAccount *account, GaimConversation *conv,
|
|
248 char **message, void *data)
|
|
249 {
|
|
250 struct crazychat *cc;
|
|
251
|
|
252 cc = (struct crazychat*)data;
|
|
253 assert(cc);
|
|
254 if (!strncmp(*message, CRAZYCHAT_INVITE_CODE,
|
|
255 strlen(CRAZYCHAT_INVITE_CODE))) {
|
|
256 return TRUE;
|
|
257 } else if (!strncmp(*message, CRAZYCHAT_ACCEPT_CODE,
|
|
258 strlen(CRAZYCHAT_ACCEPT_CODE))) {
|
|
259 return TRUE;
|
|
260 } else if (!strncmp(*message, CRAZYCHAT_READY_CODE,
|
|
261 strlen(CRAZYCHAT_READY_CODE))) {
|
|
262 return TRUE;
|
|
263 }
|
|
264
|
|
265 return FALSE;
|
|
266 }
|
|
267
|
|
268 static GtkWidget *get_config_frame(GaimPlugin *plugin)
|
|
269 {
|
|
270 GtkWidget *ret;
|
|
271 GtkWidget *frame;
|
|
272 GtkWidget *vbox, *hbox;
|
|
273 GtkWidget *drawing_area;
|
|
274 GtkWidget *label;
|
|
275 GtkAdjustment *adj;
|
|
276 GtkWidget *spinner;
|
|
277 GtkWidget *button, *button1, *button2;
|
|
278 GSList *group;
|
|
279 struct draw_info *info;
|
|
280 struct crazychat *cc;
|
|
281
|
|
282 cc = (struct crazychat*)plugin->info->extra_info;
|
|
283 assert(cc);
|
|
284
|
|
285 /* create widgets */
|
|
286
|
|
287 /* creating the config frame */
|
|
288 ret = gtk_vbox_new(FALSE, 18);
|
|
289 gtk_container_set_border_width(GTK_CONTAINER(ret), 12);
|
|
290
|
|
291 /* make the network configuration frame */
|
|
292 frame = gaim_gtk_make_frame(ret, _("Network Configuration"));
|
|
293 gtk_widget_show(frame);
|
|
294
|
|
295 /* add boxes for packing purposes */
|
|
296 vbox = gtk_vbox_new(FALSE, 0);
|
|
297 gtk_box_pack_start(GTK_BOX(frame), vbox, TRUE, TRUE, 0);
|
|
298 gtk_widget_show(vbox);
|
|
299
|
|
300 /* add widgets to row 1 */
|
|
301 hbox = gtk_hbox_new(FALSE, 0);
|
|
302 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
|
|
303 gtk_widget_show(hbox);
|
|
304 label = gtk_label_new(_("TCP port"));
|
|
305 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 15);
|
|
306 gtk_widget_show(label);
|
|
307 adj = (GtkAdjustment*)gtk_adjustment_new(DEFAULT_CC_PORT, 1,
|
|
308 G_MAXUSHORT, 1, 1000, 0);
|
|
309 spinner = gtk_spin_button_new(adj, 1, 0);
|
|
310 g_signal_connect(G_OBJECT(spinner), "value_changed",
|
|
311 G_CALLBACK(tcp_port_cb), cc);
|
|
312 gtk_box_pack_start(GTK_BOX(hbox), spinner, FALSE, FALSE, 0);
|
|
313 gtk_widget_show(spinner);
|
|
314 label = gtk_label_new(_("UDP port"));
|
|
315 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 15);
|
|
316 gtk_widget_show(label);
|
|
317 adj = (GtkAdjustment*)gtk_adjustment_new(DEFAULT_CC_PORT, 1,
|
|
318 G_MAXUSHORT, 1, 1000, 0);
|
|
319 spinner = gtk_spin_button_new(adj, 1, 0);
|
|
320 g_signal_connect(G_OBJECT(spinner), "value_changed",
|
|
321 G_CALLBACK(udp_port_cb), cc);
|
|
322 gtk_box_pack_start(GTK_BOX(hbox), spinner, FALSE, FALSE, 0);
|
|
323 gtk_widget_show(spinner);
|
|
324
|
|
325 /* make the feature configuration frame */
|
|
326 frame = gaim_gtk_make_frame(ret, _("Feature Calibration"));
|
|
327 gtk_widget_show(frame);
|
|
328
|
|
329 /* add hbox for packing purposes */
|
|
330 hbox = gtk_hbox_new(TRUE, 40);
|
|
331 gtk_box_pack_start(GTK_BOX(frame), hbox, TRUE, TRUE, 0);
|
|
332 gtk_widget_show(hbox);
|
|
333
|
|
334 /* add feature calibration options */
|
|
335
|
|
336 /* add vbox for packing purposes */
|
|
337 vbox = gtk_vbox_new(TRUE, 0);
|
|
338 gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
|
|
339 gtk_widget_show(vbox);
|
|
340
|
|
341 /* add enabled / disabled */
|
|
342 button1 = gtk_radio_button_new_with_label(NULL, _("Enabled"));
|
|
343 gtk_box_pack_start(GTK_BOX(vbox), button1, TRUE, TRUE, 0);
|
|
344 gtk_widget_show(button1);
|
|
345
|
|
346 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button1));
|
|
347 button2 = gtk_radio_button_new_with_label(group, _("Disabled"));
|
|
348 gtk_box_pack_start(GTK_BOX(vbox), button2, TRUE, TRUE, 0);
|
|
349 gtk_widget_show(button2);
|
|
350
|
|
351 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button1),
|
|
352 cc->features_state);
|
|
353 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button2),
|
|
354 !cc->features_state);
|
|
355 g_signal_connect_swapped(G_OBJECT(button1), "toggled",
|
|
356 G_CALLBACK(features_enable_cb), cc);
|
|
357
|
|
358 /* add vbox for packing purposes */
|
|
359 vbox = gtk_vbox_new(TRUE, 0);
|
|
360 gtk_box_pack_end(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
|
|
361 gtk_widget_show(vbox);
|
|
362
|
|
363 /* add calibrate button */
|
|
364 button = gtk_button_new_with_label("Calibrate");
|
|
365 gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, FALSE, 0);
|
|
366 gtk_widget_show(button);
|
|
367
|
|
368 gtk_widget_show(ret);
|
|
369
|
|
370 return ret;
|
|
371 }
|
|
372
|
|
373 static void tcp_port_cb(GtkSpinButton *spin, struct crazychat *cc)
|
|
374 {
|
|
375 assert(spin);
|
|
376 assert(cc);
|
|
377 cc->tcp_port = gtk_spin_button_get_value_as_int(spin);
|
|
378 Debug("New tcp port: %d\n", cc->tcp_port);
|
|
379 }
|
|
380
|
|
381 static void udp_port_cb(GtkSpinButton *spin, struct crazychat *cc)
|
|
382 {
|
|
383 assert(spin);
|
|
384 assert(cc);
|
|
385 cc->udp_port = gtk_spin_button_get_value_as_int(spin);
|
|
386 Debug("New udp port: %d\n", cc->udp_port);
|
|
387 }
|
|
388
|
|
389 static void features_enable_cb(struct crazychat *cc)
|
|
390 {
|
|
391 Debug("Changing features state\n");
|
|
392 cc->features_state = !cc->features_state;
|
|
393 if (cc->features_state) {
|
|
394 cc->input_data = init_input(cc);
|
|
395 } else {
|
|
396 if (cc->input_data) {
|
|
397 gtk_widget_destroy(cc->input_data->widget);
|
|
398 }
|
|
399 }
|
|
400 }
|
|
401
|
|
402 static gboolean cc_signed_on(GaimConnection *gc, void *plugin)
|
|
403 {
|
|
404 struct crazychat *extra;
|
|
405 void *conv_handle;
|
|
406
|
|
407 assert(plugin);
|
|
408 extra = (struct crazychat*)((GaimPlugin*)plugin)->info->extra_info;
|
|
409 gaim_signal_disconnect
|
|
410 (gaim_connections_get_handle(), "signed-on",
|
|
411 plugin, GAIM_CALLBACK(cc_signed_on));
|
|
412 gaim_signal_connect(GAIM_GTK_BLIST
|
|
413 (gaim_get_blist()),
|
|
414 "drawing-menu", plugin,
|
|
415 GAIM_CALLBACK(cc_buddy_menu), NULL);
|
|
416 conv_handle = gaim_conversations_get_handle();
|
|
417 gaim_signal_connect(conv_handle, "received-im-msg", plugin,
|
|
418 GAIM_CALLBACK(receive_im_cb), extra);
|
|
419 gaim_signal_connect(conv_handle, "displaying-im-msg", plugin,
|
|
420 GAIM_CALLBACK(display_im_cb), extra);
|
|
421 return FALSE;
|
|
422 }
|
|
423
|
|
424 static gboolean plugin_load(GaimPlugin *plugin)
|
|
425 {
|
|
426 GaimBuddyList *buddy_list;
|
|
427 void *conv_handle;
|
|
428
|
|
429 if (cc_init_gtk_gl())
|
|
430 return FALSE;
|
|
431
|
|
432 cc_init(&cc_info);
|
|
433 buddy_list = gaim_get_blist();
|
|
434 if (buddy_list) {
|
|
435 gaim_signal_connect(GAIM_GTK_BLIST
|
|
436 (buddy_list),
|
|
437 "drawing-menu", plugin,
|
|
438 GAIM_CALLBACK(cc_buddy_menu), NULL);
|
|
439 conv_handle = gaim_conversations_get_handle();
|
|
440 gaim_signal_connect(conv_handle, "received-im-msg", plugin,
|
|
441 GAIM_CALLBACK(receive_im_cb), &cc_info);
|
|
442 gaim_signal_connect(conv_handle, "displaying-im-msg", plugin,
|
|
443 GAIM_CALLBACK(display_im_cb), &cc_info);
|
|
444 } else {
|
|
445 gaim_signal_connect
|
|
446 (gaim_connections_get_handle(), "signed-on",
|
|
447 plugin, GAIM_CALLBACK(cc_signed_on), plugin);
|
|
448 }
|
|
449
|
|
450 Debug("CrazyChat plugin loaded.\n");
|
|
451
|
|
452 return TRUE;
|
|
453 }
|
|
454
|
|
455 static gboolean plugin_unload(GaimPlugin *plugin)
|
|
456 {
|
|
457 void *conv_handle;
|
|
458 struct crazychat *extra;
|
|
459 assert(plugin);
|
|
460 extra = (struct crazychat*) plugin->info->extra_info;
|
|
461 cc_destroy(extra);
|
|
462 conv_handle = gaim_conversations_get_handle();
|
|
463 gaim_signal_disconnect(GAIM_GTK_BLIST
|
|
464 (gaim_get_blist()),
|
|
465 "drawing-menu", plugin,
|
|
466 GAIM_CALLBACK(cc_buddy_menu));
|
|
467 gaim_signal_disconnect(conv_handle, "received-im", plugin,
|
|
468 GAIM_CALLBACK(receive_im_cb));
|
|
469 gaim_signal_disconnect(conv_handle, "displaying-im-msg", plugin,
|
|
470 GAIM_CALLBACK(display_im_cb));
|
|
471 Debug("CrazyChat plugin unloaded.\n");
|
|
472 return TRUE;
|
|
473 }
|
|
474
|
|
475 static void init_plugin(GaimPlugin *plugin)
|
|
476 {
|
|
477 gtk_gl_init(NULL, NULL);
|
|
478 memset(&cc_info, 0, sizeof(cc_info));
|
|
479 Debug("CrazyChat plugin initialized\n");
|
|
480 }
|
|
481
|
|
482 GAIM_INIT_PLUGIN(crazychat, init_plugin, info)
|