gee
oldstatus
2005-09-19, Nathan Walp
#define AUTORECON_PLUGIN_ID "core-autorecon" I use a struct here, but the visible/invisible isn't yet supported in this plugin, so this is more for future implementation of those static GHashTable *hash = NULL; static GHashTable *awayStates = NULL; #define AUTORECON_OPT "/plugins/core/autorecon" #define OPT_HIDE_CONNECTED AUTORECON_OPT "/hide_connected_error" #define OPT_HIDE_CONNECTING AUTORECON_OPT "/hide_connecting_error" #define OPT_RESTORE_STATE AUTORECON_OPT "/restore_state" /* storage of original (old_ops) and modified (new_ops) ui ops to allow us to intercept calls to report_disconnect */ static GaimConnectionUiOps *old_ops = NULL; static GaimConnectionUiOps *new_ops = NULL; static void report_disconnect(GaimConnection *gc, const char *text) { if(old_ops == NULL || old_ops->report_disconnect == NULL) { /* there's nothing to call through to, so don't bother } else if(gc->state == GAIM_CONNECTED && gaim_prefs_get_bool(OPT_HIDE_CONNECTED)) { /* this is a connected error, and we're hiding those */ gaim_debug(GAIM_DEBUG_INFO, "autorecon", "hid disconnect error message (%s)\n", text); } else if(gc->state == GAIM_CONNECTING && gaim_prefs_get_bool(OPT_HIDE_CONNECTING)) { /* this is a connecting error, and we're hiding those */ gaim_debug(GAIM_DEBUG_INFO, "autorecon", "hid error message while connecting (%s)\n", text); /* if we haven't returned by now, then let's pass to the real old_ops->report_disconnect(gc, text); static gboolean do_signon(gpointer data) { GaimAccount *account = data; gaim_debug(GAIM_DEBUG_INFO, "autorecon", "do_signon called\n"); g_return_val_if_fail(account != NULL, FALSE); info = g_hash_table_lookup(hash, account); if (g_list_index(gaim_accounts_get_all(), account) < 0) gaim_debug(GAIM_DEBUG_INFO, "autorecon", "calling gaim_account_connect\n"); gaim_account_connect(account); gaim_debug(GAIM_DEBUG_INFO, "autorecon", "done calling gaim_account_connect\n"); static void reconnect(GaimConnection *gc, void *m) { g_return_if_fail(gc != NULL); account = gaim_connection_get_account(gc); info = g_hash_table_lookup(hash, account); info = g_new0(GaimAutoRecon, 1); g_hash_table_insert(hash, account, info); info->delay = MIN(2 * info->delay, MAXTIME); g_source_remove(info->timeout); info->timeout = g_timeout_add(info->delay, do_signon, account); } else if (info != NULL) { g_hash_table_remove(hash, account); g_hash_table_remove(awayStates, account); static void save_state(GaimAccount *account, const char *state, const char *message) { /* Saves whether the account is back/away/visible/invisible */ if (!strcmp(state,GAIM_AWAY_CUSTOM)) { info = g_new0(GaimAwayState, 1); g_hash_table_insert(awayStates, account, info); } else if(!strcmp(state,"Back")) g_hash_table_remove(awayStates, account); static void restore_state(GaimConnection *gc, void *m) { /* Restore the state to what it was before the disconnect */ g_return_if_fail(gc != NULL); account = gaim_connection_get_account(gc); /* only restore the state if the user says so */ if(gaim_prefs_get_bool(OPT_RESTORE_STATE)) { state = g_hash_table_lookup(awayStates, account); serv_set_away(gc, state->state, state->message); /* we reconnected, remove from the hash table of disconnected accounts */ g_hash_table_remove(hash, account); free_auto_recon(gpointer data) GaimAutoRecon *info = data; g_source_remove(info->timeout); plugin_load(GaimPlugin *plugin) /* this was the suggested way to override a single function of the real ui ops. However, there's a mild concern of having more than one bit of code making a new ui op call-through copy. If plugins A and B both override the ui ops (in that order), B thinks that the overridden ui ops A created was the original. If A unloads first, and swaps out and frees its overridden version, then B is calling through to a free'd ui op. There needs to be a way to "stack up" overridden ui ops or something... I have a good idea of how to write such a creature if someone wants it done. - siege 2004-04-20 */ /* get old ops, make a copy with a minor change */ old_ops = gaim_connections_get_ui_ops(); new_ops = (GaimConnectionUiOps *) g_memdup(old_ops, sizeof(GaimConnectionUiOps)); new_ops->report_disconnect = report_disconnect; gaim_connections_set_ui_ops(new_ops); hash = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, awayStates = g_hash_table_new(g_int_hash, g_int_equal); gaim_signal_connect(gaim_connections_get_handle(), "signed-off", plugin, GAIM_CALLBACK(reconnect), NULL); gaim_signal_connect(gaim_connections_get_handle(), "signed-on", plugin, GAIM_CALLBACK(restore_state), NULL); gaim_signal_connect(gaim_accounts_get_handle(), "account-away", plugin, GAIM_CALLBACK(save_state), NULL); plugin_unload(GaimPlugin *plugin) gaim_signal_disconnect(gaim_connections_get_handle(), "signed-off", plugin, GAIM_CALLBACK(reconnect)); gaim_signal_disconnect(gaim_connections_get_handle(), "signed-on", plugin, GAIM_CALLBACK(restore_state)); gaim_signal_disconnect(gaim_accounts_get_handle(), "account-away", plugin, GAIM_CALLBACK(save_state)); g_hash_table_destroy(hash); g_hash_table_destroy(awayStates); gaim_connections_set_ui_ops(old_ops); old_ops = new_ops = NULL; static GaimPluginPrefFrame *get_plugin_pref_frame(GaimPlugin *plugin) { GaimPluginPrefFrame *frame = gaim_plugin_pref_frame_new(); pref = gaim_plugin_pref_new_with_label(_("Error Message Suppression")); gaim_plugin_pref_frame_add(frame, pref); pref = gaim_plugin_pref_new_with_name_and_label(OPT_HIDE_CONNECTED, _("Hide Disconnect Errors")); gaim_plugin_pref_frame_add(frame, pref); pref = gaim_plugin_pref_new_with_name_and_label(OPT_HIDE_CONNECTING, gaim_plugin_pref_frame_add(frame, pref); pref = gaim_plugin_pref_new_with_name_and_label(OPT_RESTORE_STATE, _("Restore Away State On Reconnect")); gaim_plugin_pref_frame_add(frame, pref); static GaimPluginUiInfo pref_info = { static GaimPluginInfo info = GAIM_PLUGIN_STANDARD, /**< type */ NULL, /**< ui_requirement */ NULL, /**< dependencies */ GAIM_PRIORITY_DEFAULT, /**< priority */ AUTORECON_PLUGIN_ID, /**< id */ N_("Auto-Reconnect"), /**< name */ N_("When you are kicked offline, this reconnects you."), N_("When you are kicked offline, this reconnects you."), "Eric Warmenhoven <eric@warmenhoven.org>", /**< author */ GAIM_WEBSITE, /**< homepage */ plugin_load, /**< load */ plugin_unload, /**< unload */ &pref_info, /**< prefs_info */ init_plugin(GaimPlugin *plugin) gaim_prefs_add_none(AUTORECON_OPT); gaim_prefs_add_bool(OPT_HIDE_CONNECTED, FALSE); gaim_prefs_add_bool(OPT_HIDE_CONNECTING, FALSE); gaim_prefs_add_bool(OPT_RESTORE_STATE, TRUE); GAIM_INIT_PLUGIN(autorecon, init_plugin, info)