Mercurial > pidgin
comparison src/plugin.c @ 6822:7dba3e17cb21
[gaim-migrate @ 7366]
Added plugin IPC. Its use is shown in plugins/ipc-test-server.c and
plugins/ipc-test-client.c.
committer: Tailor Script <tailor@pidgin.im>
| author | Christian Hammond <chipx86@chipx86.com> |
|---|---|
| date | Sat, 13 Sep 2003 09:31:03 +0000 |
| parents | 1b91cb6be4c3 |
| children | abd3c684da31 |
comparison
equal
deleted
inserted
replaced
| 6821:636b5215552e | 6822:7dba3e17cb21 |
|---|---|
| 15 * | 15 * |
| 16 * You should have received a copy of the GNU General Public License | 16 * You should have received a copy of the GNU General Public License |
| 17 * along with this program; if not, write to the Free Software | 17 * along with this program; if not, write to the Free Software |
| 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 */ | 19 */ |
| 20 | |
| 21 /* | |
| 22 * ---------------- | |
| 23 * The Plug-in plugin | |
| 24 * | |
| 25 * Plugin support is currently being maintained by Mike Saraf | |
| 26 * msaraf@dwc.edu | |
| 27 * | |
| 28 * Well, I didn't see any work done on it for a while, so I'm going to try | |
| 29 * my hand at it. - Eric warmenhoven@yahoo.com | |
| 30 * | |
| 31 * Mike is my roomate. I can assure you that he's lazy :-P | |
| 32 * -- Rob rob@marko.net | |
| 33 * | |
| 34 * Yeah, well now I'm re-writing a good portion of it! The perl stuff was | |
| 35 * a hack. Tsk tsk! -- Christian <chipx86@gnupdate.org> | |
| 36 */ | |
| 37 #include "internal.h" | 20 #include "internal.h" |
| 38 | 21 |
| 39 #include "accountopt.h" | 22 #include "accountopt.h" |
| 40 #include "debug.h" | 23 #include "debug.h" |
| 41 #include "notify.h" | 24 #include "notify.h" |
| 52 #else | 35 #else |
| 53 # define PLUGIN_EXT ".so" | 36 # define PLUGIN_EXT ".so" |
| 54 #endif | 37 #endif |
| 55 #endif | 38 #endif |
| 56 | 39 |
| 40 typedef struct | |
| 41 { | |
| 42 GHashTable *commands; | |
| 43 size_t command_count; | |
| 44 | |
| 45 } GaimPluginIpcInfo; | |
| 46 | |
| 47 typedef struct | |
| 48 { | |
| 49 GaimCallback func; | |
| 50 GaimSignalMarshalFunc marshal; | |
| 51 | |
| 52 int num_params; | |
| 53 GaimValue **params; | |
| 54 GaimValue *ret_value; | |
| 55 | |
| 56 } GaimPluginIpcCommand; | |
| 57 | |
| 57 static GList *loaded_plugins = NULL; | 58 static GList *loaded_plugins = NULL; |
| 58 static GList *plugins = NULL; | 59 static GList *plugins = NULL; |
| 59 static GList *plugin_loaders = NULL; | 60 static GList *plugin_loaders = NULL; |
| 60 static GList *protocol_plugins = NULL; | 61 static GList *protocol_plugins = NULL; |
| 61 | 62 |
| 393 if (loader_info->load != NULL) | 394 if (loader_info->load != NULL) |
| 394 loader_info->unload(plugin); | 395 loader_info->unload(plugin); |
| 395 } | 396 } |
| 396 | 397 |
| 397 gaim_signals_disconnect_by_handle(plugin); | 398 gaim_signals_disconnect_by_handle(plugin); |
| 399 gaim_plugin_ipc_unregister_all(plugin); | |
| 398 | 400 |
| 399 /* TODO */ | 401 /* TODO */ |
| 400 if (unload_cb != NULL) | 402 if (unload_cb != NULL) |
| 401 unload_cb(plugin, unload_cb_data); | 403 unload_cb(plugin, unload_cb_data); |
| 402 | 404 |
| 497 g_return_val_if_fail(plugin != NULL, FALSE); | 499 g_return_val_if_fail(plugin != NULL, FALSE); |
| 498 | 500 |
| 499 return plugin->loaded; | 501 return plugin->loaded; |
| 500 } | 502 } |
| 501 | 503 |
| 504 /************************************************************************** | |
| 505 * Plugin IPC | |
| 506 **************************************************************************/ | |
| 507 static void | |
| 508 destroy_ipc_info(void *data) | |
| 509 { | |
| 510 GaimPluginIpcCommand *ipc_command = (GaimPluginIpcCommand *)data; | |
| 511 int i; | |
| 512 | |
| 513 for (i = 0; i < ipc_command->num_params; i++) | |
| 514 gaim_value_destroy(ipc_command->params[i]); | |
| 515 | |
| 516 if (ipc_command->ret_value != NULL) | |
| 517 gaim_value_destroy(ipc_command->ret_value); | |
| 518 | |
| 519 g_free(ipc_command); | |
| 520 } | |
| 521 | |
| 522 gboolean | |
| 523 gaim_plugin_ipc_register(GaimPlugin *plugin, const char *command, | |
| 524 GaimCallback func, GaimSignalMarshalFunc marshal, | |
| 525 GaimValue *ret_value, int num_params, ...) | |
| 526 { | |
| 527 GaimPluginIpcInfo *ipc_info; | |
| 528 GaimPluginIpcCommand *ipc_command; | |
| 529 | |
| 530 g_return_val_if_fail(plugin != NULL, FALSE); | |
| 531 g_return_val_if_fail(command != NULL, FALSE); | |
| 532 g_return_val_if_fail(func != NULL, FALSE); | |
| 533 g_return_val_if_fail(marshal != NULL, FALSE); | |
| 534 | |
| 535 if (plugin->ipc_data == NULL) | |
| 536 { | |
| 537 ipc_info = plugin->ipc_data = g_new0(GaimPluginIpcInfo, 1); | |
| 538 ipc_info->commands = g_hash_table_new_full(g_str_hash, g_str_equal, | |
| 539 g_free, destroy_ipc_info); | |
| 540 } | |
| 541 else | |
| 542 ipc_info = (GaimPluginIpcInfo *)plugin->ipc_data; | |
| 543 | |
| 544 ipc_command = g_new0(GaimPluginIpcCommand, 1); | |
| 545 ipc_command->func = func; | |
| 546 ipc_command->marshal = marshal; | |
| 547 ipc_command->num_params = num_params; | |
| 548 ipc_command->ret_value = ret_value; | |
| 549 | |
| 550 if (num_params > 0) | |
| 551 { | |
| 552 va_list args; | |
| 553 int i; | |
| 554 | |
| 555 ipc_command->params = g_new0(GaimValue *, num_params); | |
| 556 | |
| 557 va_start(args, num_params); | |
| 558 | |
| 559 for (i = 0; i < num_params; i++) | |
| 560 ipc_command->params[i] = va_arg(args, GaimValue *); | |
| 561 | |
| 562 va_end(args); | |
| 563 } | |
| 564 | |
| 565 g_hash_table_replace(ipc_info->commands, g_strdup(command), ipc_command); | |
| 566 | |
| 567 ipc_info->command_count++; | |
| 568 | |
| 569 return TRUE; | |
| 570 } | |
| 571 | |
| 572 void | |
| 573 gaim_plugin_ipc_unregister(GaimPlugin *plugin, const char *command) | |
| 574 { | |
| 575 GaimPluginIpcInfo *ipc_info; | |
| 576 | |
| 577 g_return_if_fail(plugin != NULL); | |
| 578 g_return_if_fail(command != NULL); | |
| 579 | |
| 580 ipc_info = (GaimPluginIpcInfo *)plugin->ipc_data; | |
| 581 | |
| 582 if (ipc_info == NULL || | |
| 583 g_hash_table_lookup(ipc_info->commands, command) == NULL) | |
| 584 { | |
| 585 gaim_debug_error("plugins", | |
| 586 "IPC command '%s' was not registered for plugin %s\n", | |
| 587 command, plugin->info->name); | |
| 588 return; | |
| 589 } | |
| 590 | |
| 591 g_hash_table_remove(ipc_info->commands, command); | |
| 592 | |
| 593 ipc_info->command_count--; | |
| 594 | |
| 595 if (ipc_info->command_count == 0) | |
| 596 { | |
| 597 g_hash_table_destroy(ipc_info->commands); | |
| 598 g_free(ipc_info); | |
| 599 | |
| 600 plugin->ipc_data = NULL; | |
| 601 } | |
| 602 } | |
| 603 | |
| 604 void | |
| 605 gaim_plugin_ipc_unregister_all(GaimPlugin *plugin) | |
| 606 { | |
| 607 GaimPluginIpcInfo *ipc_info; | |
| 608 | |
| 609 g_return_if_fail(plugin != NULL); | |
| 610 | |
| 611 if (plugin->ipc_data == NULL) | |
| 612 return; /* Silently ignore it. */ | |
| 613 | |
| 614 ipc_info = (GaimPluginIpcInfo *)plugin->ipc_data; | |
| 615 | |
| 616 g_hash_table_destroy(ipc_info->commands); | |
| 617 g_free(ipc_info); | |
| 618 | |
| 619 plugin->ipc_data = NULL; | |
| 620 } | |
| 621 | |
| 622 gboolean | |
| 623 gaim_plugin_ipc_get_params(GaimPlugin *plugin, const char *command, | |
| 624 GaimValue **ret_value, int *num_params, | |
| 625 GaimValue ***params) | |
| 626 { | |
| 627 GaimPluginIpcInfo *ipc_info; | |
| 628 GaimPluginIpcCommand *ipc_command; | |
| 629 | |
| 630 g_return_val_if_fail(plugin != NULL, FALSE); | |
| 631 g_return_val_if_fail(command != NULL, FALSE); | |
| 632 | |
| 633 ipc_info = (GaimPluginIpcInfo *)plugin->ipc_data; | |
| 634 | |
| 635 if (ipc_info == NULL || | |
| 636 (ipc_command = g_hash_table_lookup(ipc_info->commands, | |
| 637 command)) == NULL) | |
| 638 { | |
| 639 gaim_debug_error("plugins", | |
| 640 "IPC command '%s' was not registered for plugin %s\n", | |
| 641 command, plugin->info->name); | |
| 642 | |
| 643 return FALSE; | |
| 644 } | |
| 645 | |
| 646 if (num_params != NULL) | |
| 647 *num_params = ipc_command->num_params; | |
| 648 | |
| 649 if (params != NULL) | |
| 650 *params = ipc_command->params; | |
| 651 | |
| 652 if (ret_value != NULL) | |
| 653 *ret_value = ipc_command->ret_value; | |
| 654 | |
| 655 return TRUE; | |
| 656 } | |
| 657 | |
| 658 void * | |
| 659 gaim_plugin_ipc_call(GaimPlugin *plugin, const char *command, | |
| 660 gboolean *ok, ...) | |
| 661 { | |
| 662 GaimPluginIpcInfo *ipc_info; | |
| 663 GaimPluginIpcCommand *ipc_command; | |
| 664 va_list args; | |
| 665 void *ret_value; | |
| 666 | |
| 667 if (ok != NULL) | |
| 668 *ok = FALSE; | |
| 669 | |
| 670 g_return_val_if_fail(plugin != NULL, NULL); | |
| 671 g_return_val_if_fail(command != NULL, NULL); | |
| 672 | |
| 673 ipc_info = (GaimPluginIpcInfo *)plugin->ipc_data; | |
| 674 | |
| 675 if (ipc_info == NULL || | |
| 676 (ipc_command = g_hash_table_lookup(ipc_info->commands, | |
| 677 command)) == NULL) | |
| 678 { | |
| 679 gaim_debug_error("plugins", | |
| 680 "IPC command '%s' was not registered for plugin %s\n", | |
| 681 command, plugin->info->name); | |
| 682 | |
| 683 return NULL; | |
| 684 } | |
| 685 | |
| 686 va_start(args, ok); | |
| 687 ipc_command->marshal(ipc_command->func, args, NULL, &ret_value); | |
| 688 va_end(args); | |
| 689 | |
| 690 if (ok != NULL) | |
| 691 *ok = TRUE; | |
| 692 | |
| 693 return ret_value; | |
| 694 } | |
| 695 | |
| 696 /************************************************************************** | |
| 697 * Plugins subsystem | |
| 698 **************************************************************************/ | |
| 502 void | 699 void |
| 503 gaim_plugins_set_search_paths(size_t count, char **paths) | 700 gaim_plugins_set_search_paths(size_t count, char **paths) |
| 504 { | 701 { |
| 505 size_t s; | 702 size_t s; |
| 506 | 703 |
