static gboolean indicator_load(PurplePlugin *plugin) { indicator_docklet_init(plugin, &ui_ops); AppIndicator *indicator = app_indicator_new_with_path("pidgin", PIDGIN_STOCK_TRAY_AVAILABLE, APP_INDICATOR_CATEGORY_APPLICATION_STATUS, DATADIR G_DIR_SEPARATOR_S "pixmaps" G_DIR_SEPARATOR_S "pidgin" G_DIR_SEPARATOR_S "tray"); sIndicator = indicator; app_indicator_set_status(indicator, APP_INDICATOR_STATUS_ACTIVE); indicator_update_icon(purple_savedstatus_get_type(purple_savedstatus_get_current()), FALSE, FALSE); void *plugins_handle = purple_plugins_get_handle(); purple_signal_connect(plugins_handle, "plugin-load", plugin->handle, PURPLE_CALLBACK(indicator_build_menu), indicator); purple_signal_connect(plugins_handle, "plugin-unload", plugin->handle, PURPLE_CALLBACK(indicator_build_menu), indicator); indicator_build_menu(NULL, indicator); plugin->extra = indicator; pidgin_blist_visibility_manager_add(); return TRUE; }
void purple_plugins_uninit(void) { void *handle = purple_plugins_get_handle(); purple_signals_disconnect_by_handle(handle); purple_signals_unregister_by_instance(handle); while (search_paths) { g_free(search_paths->data); search_paths = g_list_delete_link(search_paths, search_paths); } }
void purple_plugins_init(void) { void *handle = purple_plugins_get_handle(); purple_plugins_add_search_path(LIBDIR); purple_signal_register(handle, "plugin-load", purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, PURPLE_TYPE_PLUGIN); purple_signal_register(handle, "plugin-unload", purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, PURPLE_TYPE_PLUGIN); }
gboolean purple_plugin_unload(PurplePlugin *plugin) { #ifdef PURPLE_PLUGINS GList *l; GList *ll; g_return_val_if_fail(plugin != NULL, FALSE); g_return_val_if_fail(purple_plugin_is_loaded(plugin), FALSE); purple_debug_info("plugins", "Unloading plugin %s\n", plugin->info->name); /* Unload all plugins that depend on this plugin. */ for (l = plugin->dependent_plugins; l != NULL; l = ll) { const char * dep_name = (const char *)l->data; PurplePlugin *dep_plugin; /* Store a pointer to the next element in the list. * This is because we'll be modifying this list in the loop. */ ll = l->next; dep_plugin = purple_plugins_find_with_id(dep_name); if (dep_plugin != NULL && purple_plugin_is_loaded(dep_plugin)) { if (!purple_plugin_unload(dep_plugin)) { g_free(plugin->error); plugin->error = g_strdup_printf(_("%s requires %s, but it failed to unload."), _(plugin->info->name), _(dep_plugin->info->name)); return FALSE; } else { #if 0 /* This isn't necessary. This has already been done when unloading dep_plugin. */ plugin->dependent_plugins = g_list_delete_link(plugin->dependent_plugins, l); #endif } } } /* Remove this plugin from each dependency's dependent_plugins list. */ for (l = plugin->info->dependencies; l != NULL; l = l->next) { const char *dep_name = (const char *)l->data; PurplePlugin *dependency; dependency = purple_plugins_find_with_id(dep_name); if (dependency != NULL) dependency->dependent_plugins = g_list_remove(dependency->dependent_plugins, plugin->info->id); else purple_debug_error("plugins", "Unable to remove from dependency list for %s\n", dep_name); } if (plugin->native_plugin) { if (plugin->info->unload && !plugin->info->unload(plugin)) return FALSE; if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL) { PurplePluginProtocolInfo *prpl_info; GList *l; prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); for (l = prpl_info->user_splits; l != NULL; l = l->next) purple_account_user_split_destroy(l->data); for (l = prpl_info->protocol_options; l != NULL; l = l->next) purple_account_option_destroy(l->data); if (prpl_info->user_splits != NULL) { g_list_free(prpl_info->user_splits); prpl_info->user_splits = NULL; } if (prpl_info->protocol_options != NULL) { g_list_free(prpl_info->protocol_options); prpl_info->protocol_options = NULL; } } } else { PurplePlugin *loader; PurplePluginLoaderInfo *loader_info; loader = find_loader_for_plugin(plugin); if (loader == NULL) return FALSE; loader_info = PURPLE_PLUGIN_LOADER_INFO(loader); if (loader_info->unload && !loader_info->unload(plugin)) return FALSE; } /* cancel any pending dialogs the plugin has */ purple_request_close_with_handle(plugin); purple_notify_close_with_handle(plugin); purple_signals_disconnect_by_handle(plugin); purple_plugin_ipc_unregister_all(plugin); loaded_plugins = g_list_remove(loaded_plugins, plugin); if ((plugin->info != NULL) && PURPLE_IS_PROTOCOL_PLUGIN(plugin)) protocol_plugins = g_list_remove(protocol_plugins, plugin); plugins_to_disable = g_list_remove(plugins_to_disable, plugin); plugin->loaded = FALSE; /* We wouldn't be anywhere near here if the plugin wasn't loaded, so * if plugin->error is set at all, it had to be from a previous * unload failure. It's obviously okay now. */ g_free(plugin->error); plugin->error = NULL; purple_signal_emit(purple_plugins_get_handle(), "plugin-unload", plugin); purple_prefs_disconnect_by_handle(plugin); return TRUE; #else return TRUE; #endif /* PURPLE_PLUGINS */ }
gboolean purple_plugin_load(PurplePlugin *plugin) { #ifdef PURPLE_PLUGINS GList *dep_list = NULL; GList *l; g_return_val_if_fail(plugin != NULL, FALSE); if (purple_plugin_is_loaded(plugin)) return TRUE; if (purple_plugin_is_unloadable(plugin)) return FALSE; g_return_val_if_fail(plugin->error == NULL, FALSE); /* * Go through the list of the plugin's dependencies. * * First pass: Make sure all the plugins needed are probed. */ for (l = plugin->info->dependencies; l != NULL; l = l->next) { const char *dep_name = (const char *)l->data; PurplePlugin *dep_plugin; dep_plugin = purple_plugins_find_with_id(dep_name); if (dep_plugin == NULL) { char *tmp; tmp = g_strdup_printf(_("The required plugin %s was not found. " "Please install this plugin and try again."), dep_name); purple_notify_error(NULL, NULL, _("Unable to load the plugin"), tmp, NULL); g_free(tmp); g_list_free(dep_list); return FALSE; } dep_list = g_list_append(dep_list, dep_plugin); } /* Second pass: load all the required plugins. */ for (l = dep_list; l != NULL; l = l->next) { PurplePlugin *dep_plugin = (PurplePlugin *)l->data; if (!purple_plugin_is_loaded(dep_plugin)) { if (!purple_plugin_load(dep_plugin)) { char *tmp; tmp = g_strdup_printf(_("The required plugin %s was unable to load."), plugin->info->name); purple_notify_error(NULL, NULL, _("Unable to load your plugin."), tmp, NULL); g_free(tmp); g_list_free(dep_list); return FALSE; } } } /* Third pass: note that other plugins are dependencies of this plugin. * This is done separately in case we had to bail out earlier. */ for (l = dep_list; l != NULL; l = l->next) { PurplePlugin *dep_plugin = (PurplePlugin *)l->data; dep_plugin->dependent_plugins = g_list_prepend(dep_plugin->dependent_plugins, (gpointer)plugin->info->id); } g_list_free(dep_list); if (plugin->native_plugin) { if (plugin->info->load != NULL && !plugin->info->load(plugin)) return FALSE; } else { PurplePlugin *loader; PurplePluginLoaderInfo *loader_info; loader = find_loader_for_plugin(plugin); if (loader == NULL) return FALSE; loader_info = PURPLE_PLUGIN_LOADER_INFO(loader); if (loader_info->load != NULL) { if (!loader_info->load(plugin)) return FALSE; } } loaded_plugins = g_list_insert_sorted(loaded_plugins, plugin, compare_plugins); plugin->loaded = TRUE; purple_signal_emit(purple_plugins_get_handle(), "plugin-load", plugin); return TRUE; #else return TRUE; #endif /* !PURPLE_PLUGINS */ }