diff options
author | Jonny Lamb <jonny.lamb@collabora.co.uk> | 2012-04-05 12:11:59 -0400 |
---|---|---|
committer | Jonny Lamb <jonny.lamb@collabora.co.uk> | 2012-07-20 12:19:13 +0100 |
commit | eeb872711256df80c71f3dac2f8de718f0c0d64d (patch) | |
tree | a0ed3333856897de8e51c74e251390e389ad5c77 /src/muc-channel.c | |
parent | 3b045801e426844af922b5a34a86f4ca0765a6f3 (diff) | |
download | telepathy-gabble-eeb872711256df80c71f3dac2f8de718f0c0d64d.tar.gz |
muc-channel: disappear from the bus when not requested
Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
Diffstat (limited to 'src/muc-channel.c')
-rw-r--r-- | src/muc-channel.c | 93 |
1 files changed, 91 insertions, 2 deletions
diff --git a/src/muc-channel.c b/src/muc-channel.c index 4e81ee1c2..cb675f287 100644 --- a/src/muc-channel.c +++ b/src/muc-channel.c @@ -125,6 +125,8 @@ enum NEW_CALL, #endif + APPEARED, + LAST_SIGNAL }; @@ -134,6 +136,7 @@ static guint signals[LAST_SIGNAL] = {0}; enum { PROP_STATE = 1, + PROP_INITIALLY_REGISTER, PROP_INVITED, PROP_INVITATION_MESSAGE, PROP_SELF_JID, @@ -167,6 +170,8 @@ struct _GabbleMucChannelPrivate { GabbleMucState state; gboolean closing; + gboolean autoclose; + gboolean initially_register; guint join_timer_id; guint poll_timer_id; @@ -423,7 +428,8 @@ gabble_muc_channel_constructed (GObject *obj) } /* register object on the bus */ - tp_base_channel_register (base); + if (priv->initially_register) + tp_base_channel_register (base); /* initialize group mixin */ tp_group_mixin_init (obj, @@ -873,6 +879,9 @@ gabble_muc_channel_get_property (GObject *object, case PROP_STATE: g_value_set_uint (value, priv->state); break; + case PROP_INITIALLY_REGISTER: + g_value_set_boolean (value, priv->initially_register); + break; case PROP_SELF_JID: g_value_set_string (value, priv->self_jid->str); break; @@ -945,6 +954,9 @@ gabble_muc_channel_set_property (GObject *object, channel_state_changed (chan, prev_state, priv->state); break; + case PROP_INITIALLY_REGISTER: + priv->initially_register = g_value_get_boolean (value); + break; case PROP_INVITED: priv->invited = g_value_get_boolean (value); break; @@ -1071,6 +1083,12 @@ gabble_muc_channel_class_init (GabbleMucChannelClass *gabble_muc_channel_class) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_STATE, param_spec); + param_spec = g_param_spec_boolean ("initially-register", "Initially register", + "whether to register the channel on the bus on creation", + TRUE, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_INITIALLY_REGISTER, param_spec); + param_spec = g_param_spec_boolean ("invited", "Invited?", "Whether the user has been invited to the channel.", FALSE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS); @@ -1226,6 +1244,14 @@ gabble_muc_channel_class_init (GabbleMucChannelClass *gabble_muc_channel_class) * wants a value type, not an interface. */ G_TYPE_NONE, 1, TP_TYPE_BASE_CHANNEL); + signals[APPEARED] = g_signal_new ("appeared", + G_OBJECT_CLASS_TYPE (gabble_muc_channel_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + #ifdef ENABLE_VOIP signals[NEW_CALL] = g_signal_new ("new-call", G_OBJECT_CLASS_TYPE (gabble_muc_channel_class), @@ -1525,9 +1551,32 @@ close_channel (GabbleMucChannel *chan, const gchar *reason, GError error = { TP_ERROR, TP_ERROR_CANCELLED, "Muc channel closed below us" }; - if (tp_base_channel_is_destroyed (base) || priv->closing) + if (tp_base_channel_is_destroyed (base)) return; + /* if priv->closing is TRUE, we're waiting for the MUC to echo our + * presence. however, if we're being asked to close again, but this + * time without letting the muc know, let's actually close. if we + * don't then the channel won't disappear from the bus properly. */ + if (priv->closing && !inform_muc) + { + clear_leave_timer (chan); + tp_base_channel_destroyed (base); + return; + } + + /* If inform_muc is TRUE it means that we're closing the channel + * gracefully and we don't mind if the channel doesn't actually + * close behind the scenes if a tube/call is still open. Every call + * to this function has inform_muc=FALSE, except for Channel.Close() + * and RemoveMembers(self_handle) */ + if (inform_muc && !gabble_muc_channel_can_be_closed (chan)) + { + priv->autoclose = TRUE; + tp_base_channel_disappear (base); + return; + } + DEBUG ("Closing"); /* Ensure we stay alive even while telling everyone else to abandon us. */ g_object_ref (chan); @@ -1591,6 +1640,35 @@ _gabble_muc_channel_is_ready (GabbleMucChannel *chan) return priv->ready; } +/* returns TRUE if there are no tube or Call channels open in this MUC */ +gboolean +gabble_muc_channel_can_be_closed (GabbleMucChannel *chan) +{ + GabbleMucChannelPrivate *priv = chan->priv; + + if (g_hash_table_size (priv->tubes) > 0) + return FALSE; + + if (priv->calls != NULL || priv->call_requests != NULL + || priv->call_initiating) + return FALSE; + + return TRUE; +} + +gboolean +gabble_muc_channel_get_autoclose (GabbleMucChannel *chan) +{ + return chan->priv->autoclose; +} + +void +gabble_muc_channel_set_autoclose (GabbleMucChannel *chan, + gboolean autoclose) +{ + chan->priv->autoclose = autoclose; +} + static gboolean handle_nick_conflict (GabbleMucChannel *chan, WockyStanza *stanza, @@ -2979,6 +3057,17 @@ _gabble_muc_channel_receive (GabbleMucChannel *chan, return; } + /* are we actually hidden? */ + if (!tp_base_channel_is_registered (base)) + { + DEBUG ("making MUC channel reappear!"); + tp_base_channel_reopened_with_requested (base, FALSE, sender); + g_signal_emit (chan, signals[APPEARED], 0); + } + + /* let's not autoclose now */ + chan->priv->autoclose = FALSE; + message = tp_cm_message_new (base_conn, 2); /* Header common to normal message and delivery-echo */ |