Mercurial > pidgin
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); |
