comparison src/plugins.c @ 425:ae7c762775cd

[gaim-migrate @ 435] More mods to how plugins work. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Fri, 23 Jun 2000 04:15:51 +0000
parents d6f02d7f78d8
children 11cbf8b403b6
comparison
equal deleted inserted replaced
424:22700acd9b49 425:ae7c762775cd
59 59
60 static GtkWidget *pluglist; 60 static GtkWidget *pluglist;
61 static GtkWidget *plugtext; 61 static GtkWidget *plugtext;
62 static GtkWidget *plugwindow; 62 static GtkWidget *plugwindow;
63 63
64 static GtkWidget *config; 64 static GtkWidget *config = NULL;
65 static guint confighandle = 0; 65 static guint confighandle = 0;
66 66
67 /* --------------- Function Declarations --------------------- */ 67 /* --------------- Function Declarations --------------------- */
68 68
69 void show_plugins (GtkWidget *, gpointer); 69 void show_plugins (GtkWidget *, gpointer);
70 void load_plugin (char *); 70 void load_plugin (char *);
71 71
72 void gaim_signal_connect (void *, enum gaim_event, void *, void *); 72 void gaim_signal_connect (void *, enum gaim_event, void *, void *);
73 void gaim_signal_disconnect(void *, enum gaim_event, void *); 73 void gaim_signal_disconnect(void *, enum gaim_event, void *);
74 void gaim_plugin_unload (void *);
74 75
75 static void destroy_plugins (GtkWidget *, gpointer); 76 static void destroy_plugins (GtkWidget *, gpointer);
76 static void load_file (GtkWidget *, gpointer); 77 static void load_file (GtkWidget *, gpointer);
77 static void load_which_plugin(GtkWidget *, gpointer); 78 static void load_which_plugin(GtkWidget *, gpointer);
78 static void unload (GtkWidget *, gpointer); 79 static void unload (GtkWidget *, gpointer);
137 plugin_dialog = NULL; 138 plugin_dialog = NULL;
138 } 139 }
139 140
140 void load_plugin(char *filename) { 141 void load_plugin(char *filename) {
141 struct gaim_plugin *plug; 142 struct gaim_plugin *plug;
143 GList *c = plugins;
142 int (*gaim_plugin_init)(); 144 int (*gaim_plugin_init)();
143 char *(*gaim_plugin_error)(int); 145 char *(*gaim_plugin_error)(int);
144 char *(*cfunc)(); 146 char *(*cfunc)();
145 char *error; 147 char *error;
146 int retval; 148 int retval;
147 char *plugin_error; 149 char *plugin_error;
148 150
149 if (filename == NULL) return; 151 if (filename == NULL) return;
152 /* i shouldn't be checking based solely on path, but i'm lazy */
153 while (c) {
154 plug = (struct gaim_plugin *)c->data;
155 if (!strcmp(filename, plug->filename)) {
156 sprintf(debug_buff, _("Already loaded %s, "
157 "not reloading.\n"), filename);
158 debug_print(debug_buff);
159 return;
160 }
161 c = c->next;
162 }
150 plug = g_malloc(sizeof *plug); 163 plug = g_malloc(sizeof *plug);
151 if (filename[0] != '/') { 164 if (filename[0] != '/') {
152 char *buf = g_malloc(BUF_LEN); 165 char *buf = g_malloc(BUF_LEN);
153 g_snprintf(buf, BUF_LEN - 1, "%s/%s", getenv("HOME"), PLUGIN_DIR); 166 g_snprintf(buf, BUF_LEN - 1, "%s/%s", getenv("HOME"), PLUGIN_DIR);
154 plug->filename = g_malloc(strlen(buf) + strlen(filename) + 1); 167 plug->filename = g_malloc(strlen(buf) + strlen(filename) + 1);
155 sprintf(plug->filename, "%s%s", buf, filename); 168 sprintf(plug->filename, "%s%s", buf, filename);
156 } else 169 } else
157 plug->filename = g_strdup(filename); 170 plug->filename = g_strdup(filename);
158 sprintf(debug_buff, "Loading %s\n", filename); 171 sprintf(debug_buff, "Loading %s\n", filename);
159 debug_print(debug_buff); 172 debug_print(debug_buff);
160 /* do NOT OR with RTLD_GLOBAL, otherwise plugins may conflict 173 /* do NOT `OR' with RTLD_GLOBAL, otherwise plugins may conflict
161 * (it's really just a way to work around other people's bad 174 * (it's really just a way to work around other people's bad
162 * programming, by not using RTLD_GLOBAL :P ) */ 175 * programming, by not using RTLD_GLOBAL :P ) */
163 plug->handle = dlopen(plug->filename, RTLD_LAZY); 176 plug->handle = dlopen(plug->filename, RTLD_LAZY);
164 if (!plug->handle) { 177 if (!plug->handle) {
165 error = (char *)dlerror(); 178 error = (char *)dlerror();
343 GList *plugs = plugins; 356 GList *plugs = plugins;
344 struct gaim_plugin *p; 357 struct gaim_plugin *p;
345 GtkWidget *label; 358 GtkWidget *label;
346 GtkWidget *list_item; 359 GtkWidget *list_item;
347 360
348 if (pluglist == NULL) return; 361 if (plugwindow == NULL) return;
349 362
350 gtk_list_clear_items(GTK_LIST(pluglist), 0, -1); 363 gtk_list_clear_items(GTK_LIST(pluglist), 0, -1);
351 while (plugs) { 364 while (plugs) {
352 p = (struct gaim_plugin *)plugs->data; 365 p = (struct gaim_plugin *)plugs->data;
353 label = gtk_label_new(p->filename); 366 label = gtk_label_new(p->filename);
374 void unload(GtkWidget *w, gpointer data) { 387 void unload(GtkWidget *w, gpointer data) {
375 GList *i; 388 GList *i;
376 struct gaim_plugin *p; 389 struct gaim_plugin *p;
377 void (*gaim_plugin_remove)(); 390 void (*gaim_plugin_remove)();
378 char *error; 391 char *error;
379 GList *c = callbacks;
380 struct gaim_callback *g;
381 392
382 i = GTK_LIST(pluglist)->selection; 393 i = GTK_LIST(pluglist)->selection;
383 394
384 if (i == NULL) return; 395 if (i == NULL) return;
385 396
386 p = gtk_object_get_user_data(GTK_OBJECT(i->data)); 397 p = gtk_object_get_user_data(GTK_OBJECT(i->data));
387 sprintf(debug_buff, "Unloading %s\n", p->filename);
388 debug_print(debug_buff);
389 398
390 gaim_plugin_remove = dlsym(p->handle, "gaim_plugin_remove"); 399 gaim_plugin_remove = dlsym(p->handle, "gaim_plugin_remove");
391 if ((error = (char *)dlerror()) == NULL) 400 if ((error = (char *)dlerror()) == NULL)
392 (*gaim_plugin_remove)(); 401 (*gaim_plugin_remove)();
402
403 gaim_plugin_unload(p->handle);
404 }
405
406 static void remove_callback(struct gaim_plugin *p) {
407 gtk_timeout_remove(p->remove);
408 dlclose(p->handle);
409 g_free(p);
410 }
411
412 /* gaim_plugin_unload serves 2 purposes: 1. so plugins can unload themselves
413 * 2. to make my life easier */
414 void gaim_plugin_unload(void *handle) {
415 GList *i;
416 struct gaim_plugin *p = NULL;
417 GList *c = callbacks;
418 struct gaim_callback *g;
419
420 i = plugins;
421 while (i) {
422 p = (struct gaim_plugin *)i->data;
423 if (handle == p->handle)
424 break;
425 p = NULL;
426 i = i->next;
427 }
428
429 if (!p)
430 return;
431
432 sprintf(debug_buff, "Unloading %s\n", p->filename);
433 debug_print(debug_buff);
434
393 sprintf(debug_buff, "%d callbacks to search\n", g_list_length(callbacks)); 435 sprintf(debug_buff, "%d callbacks to search\n", g_list_length(callbacks));
394 debug_print(debug_buff); 436 debug_print(debug_buff);
395 while (c) { 437 while (c) {
396 g = (struct gaim_callback *)c->data; 438 g = (struct gaim_callback *)c->data;
397 if (g->handle == p->handle) { 439 if (g->handle == p->handle) {
406 } 448 }
407 } else { 449 } else {
408 c = c->next; 450 c = c->next;
409 } 451 }
410 } 452 }
411 dlclose(p->handle); 453 p->remove = gtk_timeout_add(5000, (GtkFunction)remove_callback, p);
412 454
413 plugins = g_list_remove(plugins, p); 455 plugins = g_list_remove(plugins, p);
414 g_free(p->filename); 456 g_free(p->filename);
415 g_free(p); 457 if (config) gtk_widget_set_sensitive(config, 0);
416 gtk_widget_set_sensitive(config, 0);
417 update_show_plugins(); 458 update_show_plugins();
418 save_prefs(); 459 save_prefs();
419 } 460 }
420 461
421 void list_clicked(GtkWidget *w, struct gaim_plugin *p) { 462 void list_clicked(GtkWidget *w, struct gaim_plugin *p) {
446 487
447 void hide_plugins(GtkWidget *w, gpointer data) { 488 void hide_plugins(GtkWidget *w, gpointer data) {
448 if (plugwindow) 489 if (plugwindow)
449 gtk_widget_destroy(plugwindow); 490 gtk_widget_destroy(plugwindow);
450 plugwindow = NULL; 491 plugwindow = NULL;
492 config = NULL;
451 } 493 }
452 494
453 void gaim_signal_connect(void *handle, enum gaim_event which, 495 void gaim_signal_connect(void *handle, enum gaim_event which,
454 void *func, void *data) { 496 void *func, void *data) {
455 struct gaim_callback *call = g_malloc(sizeof *call); 497 struct gaim_callback *call = g_malloc(sizeof *call);