static void location_pep_node_changed (WockyPepService *pep, WockyBareContact *contact, WockyStanza *stanza, WockyNode *item_node, GabbleConnection *conn) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); TpBaseConnection *base = (TpBaseConnection *) conn; TpHandle handle; const gchar *jid; jid = wocky_bare_contact_get_jid (contact); handle = tp_handle_ensure (contact_repo, jid, NULL, NULL); if (handle == 0) { DEBUG ("Invalid from: %s", jid); return; } if (handle == tp_base_connection_get_self_handle (base)) /* Ignore echoed pubsub notifications */ return; update_location_from_item (conn, handle, item_node); }
void example_call_stream_accept_proposed_direction (ExampleCallStream *self) { GHashTable *updated_senders; GArray *removed_senders; if (self->priv->removed || self->priv->local_sending_state != FUTURE_SENDING_STATE_PENDING_SEND) return; g_message ("%s: SIGNALLING: Sending to server: OK, I'll send you media", self->priv->object_path); self->priv->local_sending_state = FUTURE_SENDING_STATE_SENDING; updated_senders = g_hash_table_new (NULL, NULL); removed_senders = g_array_sized_new (FALSE, FALSE, sizeof (guint), 0); g_hash_table_insert (updated_senders, GUINT_TO_POINTER (tp_base_connection_get_self_handle (self->priv->conn)), GUINT_TO_POINTER (FUTURE_SENDING_STATE_SENDING)); future_svc_call_stream_emit_senders_changed (self, updated_senders, removed_senders); g_hash_table_unref (updated_senders); g_array_free (removed_senders, TRUE); }
void ring_text_manager_add_capabilities(RingTextManager *self, guint handle, GPtrArray *returns) { RingTextManagerPrivate *priv = RING_TEXT_MANAGER(self)->priv; char const *id = ring_connection_inspect_contact(priv->connection, handle); guint selfhandle = tp_base_connection_get_self_handle( (TpBaseConnection *)priv->connection); char *destination; if (id == NULL) return; /* Some UIs create channels even if they do not intend to send anything */ /* Allow them to do so */ destination = ring_text_channel_destination(id); if (handle == selfhandle || modem_sms_is_valid_address (destination)) { g_ptr_array_add(returns, ring_contact_capability_new(handle, TP_IFACE_CHANNEL_TYPE_TEXT, TP_CONNECTION_CAPABILITY_FLAG_CREATE, RING_TEXT_CHANNEL_CAPABILITY_FLAGS)); } g_free(destination); }
const gchar * conn_util_get_bare_self_jid (GabbleConnection *conn) { TpBaseConnection *base = TP_BASE_CONNECTION (conn); TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); TpHandle self = tp_base_connection_get_self_handle (base); return tp_handle_inspect (contact_handles, self); }
static void get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { ExampleCallStream *self = EXAMPLE_CALL_STREAM (object); switch (property_id) { case PROP_OBJECT_PATH: g_value_set_string (value, self->priv->object_path); break; case PROP_INTERFACES: g_value_set_static_boxed (value, empty_strv); break; case PROP_HANDLE: g_value_set_uint (value, self->priv->handle); break; case PROP_CONNECTION: g_value_set_object (value, self->priv->conn); break; case PROP_SIMULATION_DELAY: g_value_set_uint (value, self->priv->simulation_delay); break; case PROP_LOCALLY_REQUESTED: g_value_set_boolean (value, self->priv->locally_requested); break; case PROP_SENDERS: { GHashTable *senders = g_hash_table_new (NULL, NULL); g_hash_table_insert (senders, GUINT_TO_POINTER (self->priv->handle), GUINT_TO_POINTER (self->priv->remote_sending_state)); g_hash_table_insert (senders, GUINT_TO_POINTER (tp_base_connection_get_self_handle ( self->priv->conn)), GUINT_TO_POINTER (self->priv->local_sending_state)); g_value_take_boxed (value, senders); } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } }
static gboolean rakia_nua_i_invite_cb (TpBaseConnection *conn, const RakiaNuaEvent *ev, tagi_t tags[], RakiaMediaManager *fac) { TpHandle handle; RakiaSipSession *session; struct InviteData *idata; /* figure out a handle for the identity */ handle = rakia_handle_by_requestor (conn, ev->sip); if (!handle) { MESSAGE ("incoming INVITE with invalid sender information"); nua_respond (ev->nua_handle, 400, "Invalid From address", TAG_END()); return TRUE; } DEBUG("Got incoming invite from <%s>", rakia_handle_inspect (conn, handle)); if (handle == tp_base_connection_get_self_handle (conn)) { DEBUG("cannot handle calls from self"); nua_respond (ev->nua_handle, 501, "Calls from self are not supported", TAG_END()); /* FIXME: Possible handle leak.. needs double checking ? */ return TRUE; } session = new_session (fac, ev->nua_handle, 0); /* We delay emission of NewChannel(s) until we have the data on * initial media */ idata = g_slice_new (struct InviteData); idata->fac = fac; idata->handle = handle; g_signal_connect (session, "incoming-call", G_CALLBACK (incoming_call_cb), idata); return TRUE; }
static gboolean ring_media_manager_outgoing_call(RingMediaManager *self, gpointer request, TpHandle target, TpHandle initial_remote, char const *emergency, gboolean initial_audio) { RingMediaManagerPrivate *priv = self->priv; TpHandleType htype = target ? TP_HANDLE_TYPE_CONTACT : TP_HANDLE_TYPE_NONE; char *object_path = ring_media_manager_new_object_path(self, "outgoing"); RingCallChannel *channel; TpHandle initiator; initiator = tp_base_connection_get_self_handle( TP_BASE_CONNECTION(priv->connection)); channel = (RingCallChannel *) g_object_new(RING_TYPE_CALL_CHANNEL, "connection", priv->connection, "tones", priv->tones, "object-path", object_path, "initiator-handle", initiator, "handle-type", htype, "handle", target, "peer", target, "initial-remote", initial_remote, "requested", TRUE, "initial-audio", initial_audio, "anon-modes", priv->anon_modes, "initial-emergency-service", emergency, NULL); g_free(object_path); if (initial_audio) ring_call_channel_initial_audio(channel, self, request); else ring_media_manager_emit_new_channel(self, request, channel, NULL); return TRUE; }
/* * new_im_channel: * @fac: the factory * @handle: a contact handle, for whom a channel must not yet exist * @request_token: if the channel is being created in response to a channel * request, the associated request token; otherwise, NULL. * * Creates a new 1-1 text channel to a contact. Must only be called when no 1-1 * text channel is already open to that contact. * * Returns: (transfer none): a freshly-constructed channel */ static GabbleIMChannel * new_im_channel (GabbleImFactory *fac, TpHandle handle, gpointer request_token) { GabbleImFactoryPrivate *priv = fac->priv; TpBaseConnection *conn = (TpBaseConnection *) priv->conn; GabbleIMChannel *chan; GSList *request_tokens; TpHandle initiator; g_return_val_if_fail (handle != 0, NULL); if (request_token != NULL) initiator = tp_base_connection_get_self_handle (conn); else initiator = handle; chan = g_object_new (GABBLE_TYPE_IM_CHANNEL, "connection", priv->conn, "handle", handle, "initiator-handle", initiator, "requested", (handle != initiator), NULL); tp_base_channel_register ((TpBaseChannel *) chan); g_signal_connect (chan, "closed", (GCallback) im_channel_closed_cb, fac); g_hash_table_insert (priv->channels, GUINT_TO_POINTER (handle), chan); if (request_token != NULL) request_tokens = g_slist_prepend (NULL, request_token); else request_tokens = NULL; tp_channel_manager_emit_new_channel (fac, (TpExportableChannel *) chan, request_tokens); g_slist_free (request_tokens); return chan; }
void ring_media_manager_add_capabilities(RingMediaManager *self, guint handle, GPtrArray *returns) { RingMediaManagerPrivate *priv = RING_MEDIA_MANAGER(self)->priv; char const *id = ring_connection_inspect_contact(priv->connection, handle); guint selfhandle = tp_base_connection_get_self_handle( (TpBaseConnection *)priv->connection); if (id == NULL) return; if (!ring_media_manager_is_connected (self)) return; /* XXX - should check if we are in emergency call mode only status */ if (handle == selfhandle) { if (priv->capability_flags) g_ptr_array_add(returns, ring_contact_capability_new(handle, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA, TP_CONNECTION_CAPABILITY_FLAG_CREATE | TP_CONNECTION_CAPABILITY_FLAG_INVITE, RING_MEDIA_CHANNEL_CAPABILITY_FLAGS)); } else if (modem_call_is_valid_address (id)) { g_ptr_array_add(returns, ring_contact_capability_new(handle, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA, TP_CONNECTION_CAPABILITY_FLAG_CREATE | TP_CONNECTION_CAPABILITY_FLAG_INVITE, RING_MEDIA_CHANNEL_CAPABILITY_FLAGS)); } }
static void on_modem_call_created(ModemCallService *call_service, ModemCall *modem_call, char const *destination, RingMediaManager *self) { RingMediaManagerPrivate *priv = self->priv; TpHandleRepoIface *repo; RingCallChannel *channel; TpHandle handle; char const *sos; GError *error = NULL; if (!ring_media_manager_is_connected (self)) return; channel = modem_call_get_handler(modem_call); if (channel) return; /* Call created by ring, nothing to do */ /* This is a call created outside ring, create a channel for it */ DEBUG("Freshly created call instance %s not associated with channel.", modem_call_get_name(modem_call)); repo = tp_base_connection_get_handles( (TpBaseConnection *)(self->priv->connection), TP_HANDLE_TYPE_CONTACT); error = NULL; handle = tp_handle_ensure(repo, destination, ring_network_normalization_context(), &error); if (handle == 0) { ring_warning("tp_handle_ensure:" GERROR_MSG_FMT, GERROR_MSG_CODE(error)); if (error) g_error_free(error); /* Xyzzy - modem_call_request_release() ?? */ return; } sos = modem_call_get_emergency_service(priv->call_service, destination); char *object_path = ring_media_manager_new_object_path(self, "created"); channel = (RingCallChannel *) g_object_new(RING_TYPE_CALL_CHANNEL, "connection", priv->connection, "tones", priv->tones, "object-path", object_path, "initiator-handle", tp_base_connection_get_self_handle( TP_BASE_CONNECTION(priv->connection)), "handle-type", TP_HANDLE_TYPE_CONTACT, "handle", handle, "peer", handle, "requested", TRUE, "initial-remote", handle, "initial-audio", TRUE, "anon-modes", priv->anon_modes, "call-instance", modem_call, "originating", TRUE, sos ? "initial-emergency-service" : NULL, sos, NULL); g_free(object_path); ring_media_manager_emit_new_channel(self, NULL, channel, NULL); ring_media_channel_set_state(RING_MEDIA_CHANNEL(channel), MODEM_CALL_STATE_DIALING, 0, 0); }
static gboolean rakia_media_manager_requestotron (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties, RequestMethod method) { RakiaMediaManager *self = RAKIA_MEDIA_MANAGER (manager); RakiaMediaManagerPrivate *priv = RAKIA_MEDIA_MANAGER_GET_PRIVATE (self); TpBaseConnection *conn = (TpBaseConnection *) priv->conn; TpHandleType handle_type; TpHandle handle; RakiaSipSession *session; RakiaCallChannel *channel = NULL; GError *error = NULL; GSList *request_tokens; gboolean valid = FALSE; gboolean initial_audio = FALSE; gboolean initial_video = FALSE; TpHandle self_handle = tp_base_connection_get_self_handle (conn); /* Supported modes of operation: * - RequestChannel(Contact, n) where n != 0: * channel has TargetHandle=n; * n is in remote pending; * call is started when caller calls RequestStreams. * - CreateChannel({THT: Contact, TH: n}): * channel has TargetHandle=n * n is not in the group interface at all * call is started when caller calls RequestStreams. * - EnsureChannel({THT: Contact, TH: n}): * look for a channel whose peer is n, and return that if found with * whatever properties and group membership it has; * otherwise the same as into CreateChannel */ if (tp_strdiff (tp_asv_get_string (request_properties, TP_PROP_CHANNEL_CHANNEL_TYPE), TP_IFACE_CHANNEL_TYPE_CALL)) return FALSE; if (tp_asv_get_boolean (request_properties, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, &valid) && valid) initial_audio = TRUE; if (tp_asv_get_boolean (request_properties, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, &valid) && valid) initial_audio = TRUE; if (!initial_audio && !initial_video) return FALSE; handle_type = tp_asv_get_uint32 (request_properties, TP_IFACE_CHANNEL ".TargetHandleType", NULL); handle = tp_asv_get_uint32 (request_properties, TP_IFACE_CHANNEL ".TargetHandle", NULL); if (handle_type != TP_HANDLE_TYPE_CONTACT) return FALSE; g_assert (handle != 0); if (tp_channel_manager_asv_has_unknown_properties (request_properties, media_channel_fixed_properties, named_channel_allowed_properties, &error)) goto error; /* Calls to self are problematic in terms of StreamedMedia channel * interface and its semantically required Group member changes; * we disable them until a better API is available through * Call channel type */ if (handle == self_handle) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Cannot call self"); goto error; } if (method == METHOD_ENSURE) { guint i; TpHandle peer = 0; for (i = 0; i < priv->channels->len; i++) { channel = g_ptr_array_index (priv->channels, i); g_object_get (channel, "peer", &peer, NULL); if (peer == handle) { tp_channel_manager_emit_request_already_satisfied (self, request_token, TP_EXPORTABLE_CHANNEL (channel)); return TRUE; } } } session = new_session (self, NULL, handle); channel = new_call_channel (self, self_handle, handle, request_properties, session); g_object_unref (session); request_tokens = g_slist_prepend (NULL, request_token); tp_channel_manager_emit_new_channel (self, TP_EXPORTABLE_CHANNEL (channel), request_tokens); g_slist_free (request_tokens); return TRUE; error: tp_channel_manager_emit_request_failed (self, request_token, error->domain, error->code, error->message); g_error_free (error); return TRUE; }
/** * new_call_channel * * Creates a new empty RakiaCallChannel. */ static RakiaCallChannel * new_call_channel (RakiaMediaManager *fac, TpHandle initiator, TpHandle maybe_peer, GHashTable *request_properties, RakiaSipSession *session) { RakiaMediaManagerPrivate *priv = RAKIA_MEDIA_MANAGER_GET_PRIVATE (fac); RakiaCallChannel *chan = NULL; gchar *object_path; gboolean initial_audio = FALSE; gboolean initial_video = FALSE; gboolean immutable_streams = FALSE; const gchar *dtmf_initial_tones = NULL; const gchar *initial_audio_name = NULL; const gchar *initial_video_name = NULL; TpHandle self_handle = tp_base_connection_get_self_handle (priv->conn); g_assert (initiator != 0); object_path = g_strdup_printf ("%s/CallChannel%u", tp_base_connection_get_object_path (priv->conn), priv->channel_index++); DEBUG("channel object path %s", object_path); if (request_properties != NULL) { initial_audio = tp_asv_get_boolean (request_properties, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, NULL); initial_video = tp_asv_get_boolean (request_properties, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, NULL); initial_audio_name = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO_NAME); initial_video_name = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO_NAME); dtmf_initial_tones = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_INTERFACE_DTMF_INITIAL_TONES); } g_object_get (priv->conn, "immutable-streams", &immutable_streams, NULL); chan = g_object_new (RAKIA_TYPE_CALL_CHANNEL, "connection", priv->conn, "object-path", object_path, "handle", maybe_peer, "initiator-handle", initiator, "initial-audio", initial_audio, "initial-video", initial_video, "initial-audio-name", initial_audio_name, "initial-video-name", initial_video_name, "initial-transport", TP_STREAM_TRANSPORT_TYPE_RAW_UDP, "mutable-contents", !immutable_streams, "initial-tones", dtmf_initial_tones, "sip-session", session, "stun-server", priv->stun_server ? priv->stun_server : "", "stun-port", priv->stun_port, "requested", (initiator == self_handle), NULL); g_free (object_path); g_signal_connect (chan, "closed", G_CALLBACK (call_channel_closed_cb), fac); g_ptr_array_add (priv->channels, chan); tp_base_channel_register (TP_BASE_CHANNEL (chan)); return chan; }
static gboolean _im_manager_requestotron (IdleIMManager *self, gpointer request_token, GHashTable *request_properties, gboolean require_new) { IdleIMManagerPrivate *priv = IDLE_IM_MANAGER_GET_PRIVATE (self); TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT); TpHandle handle; GError *error = NULL; TpExportableChannel *channel; if (tp_strdiff (tp_asv_get_string (request_properties, TP_IFACE_CHANNEL ".ChannelType"), TP_IFACE_CHANNEL_TYPE_TEXT)) return FALSE; if (tp_asv_get_uint32 (request_properties, TP_IFACE_CHANNEL ".TargetHandleType", NULL) != TP_HANDLE_TYPE_CONTACT) return FALSE; handle = tp_asv_get_uint32 (request_properties, TP_IFACE_CHANNEL ".TargetHandle", NULL); if (!tp_handle_is_valid (contact_repo, handle, &error)) goto error; /* Check if there are any other properties that we don't understand */ if (tp_channel_manager_asv_has_unknown_properties (request_properties, im_channel_fixed_properties, im_channel_allowed_properties, &error)) { goto error; } /* Don't support opening a channel to our self handle */ if (handle == tp_base_connection_get_self_handle (base_conn)) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Can't open a text channel to yourself"); goto error; } channel = g_hash_table_lookup (priv->channels, GUINT_TO_POINTER (handle)); if (channel == NULL) { _im_manager_new_channel (self, handle, tp_base_connection_get_self_handle (base_conn), request_token); return TRUE; } if (require_new) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "Already chatting with contact #%u in another channel", handle); goto error; } tp_channel_manager_emit_request_already_satisfied (self, request_token, channel); return TRUE; error: tp_channel_manager_emit_request_failed (self, request_token, error->domain, error->code, error->message); g_error_free (error); return TRUE; }
static gboolean example_echo_2_im_manager_request (ExampleEcho2ImManager *self, gpointer request_token, GHashTable *request_properties, gboolean require_new) { TpHandle handle; ExampleEcho2Channel *chan; GError *error = NULL; if (tp_strdiff (tp_asv_get_string (request_properties, TP_PROP_CHANNEL_CHANNEL_TYPE), TP_IFACE_CHANNEL_TYPE_TEXT)) { return FALSE; } if (tp_asv_get_uint32 (request_properties, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL) != TP_HANDLE_TYPE_CONTACT) { return FALSE; } handle = tp_asv_get_uint32 (request_properties, TP_PROP_CHANNEL_TARGET_HANDLE, NULL); g_assert (handle != 0); if (tp_channel_manager_asv_has_unknown_properties (request_properties, fixed_properties, allowed_properties, &error)) { goto error; } chan = g_hash_table_lookup (self->priv->channels, GUINT_TO_POINTER (handle)); if (chan == NULL) { new_channel (self, handle, tp_base_connection_get_self_handle (self->priv->conn), request_token); } else if (require_new) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "An echo2 channel to contact #%u already exists", handle); goto error; } else { tp_channel_manager_emit_request_already_satisfied (self, request_token, TP_EXPORTABLE_CHANNEL (chan)); } return TRUE; error: tp_channel_manager_emit_request_failed (self, request_token, error->domain, error->code, error->message); g_error_free (error); return TRUE; }
/* The remote user wants to change the direction of this stream according * to @local_send and @remote_send. Shall we let him? */ static void example_call_stream_receive_direction_request (ExampleCallStream *self, gboolean local_send, gboolean remote_send) { GHashTable *updated_senders = g_hash_table_new (NULL, NULL); /* In some protocols, streams cannot be neither sending nor receiving, so * if a stream is set to TP_MEDIA_STREAM_DIRECTION_NONE, this is equivalent * to removing it. (This is true in XMPP, for instance.) * * However, for this example we'll emulate a protocol where streams can be * directionless. */ if (local_send) { g_message ("%s: SIGNALLING: send: Please start sending me media", self->priv->object_path); if (self->priv->local_sending_state == FUTURE_SENDING_STATE_NONE) { /* ask the user for permission */ self->priv->local_sending_state = FUTURE_SENDING_STATE_PENDING_SEND; g_hash_table_insert (updated_senders, GUINT_TO_POINTER (tp_base_connection_get_self_handle ( self->priv->conn)), GUINT_TO_POINTER (FUTURE_SENDING_STATE_PENDING_SEND)); } else { /* nothing to do, we're already sending (or asking the user for * permission to do so) on that stream */ } } else { g_message ("%s: SIGNALLING: receive: Please stop sending me media", self->priv->object_path); g_message ("%s: SIGNALLING: reply: OK!", self->priv->object_path); if (self->priv->local_sending_state == FUTURE_SENDING_STATE_SENDING) { g_message ("%s: MEDIA: no longer sending media to peer", self->priv->object_path); self->priv->local_sending_state = FUTURE_SENDING_STATE_NONE; g_hash_table_insert (updated_senders, GUINT_TO_POINTER (tp_base_connection_get_self_handle ( self->priv->conn)), GUINT_TO_POINTER (FUTURE_SENDING_STATE_NONE)); } else if (self->priv->local_sending_state == FUTURE_SENDING_STATE_PENDING_SEND) { self->priv->local_sending_state = FUTURE_SENDING_STATE_NONE; g_hash_table_insert (updated_senders, GUINT_TO_POINTER (tp_base_connection_get_self_handle ( self->priv->conn)), GUINT_TO_POINTER (FUTURE_SENDING_STATE_NONE)); } else { /* nothing to do, we're not sending on that stream anyway */ } } if (remote_send) { g_message ("%s: SIGNALLING: receive: I will now send you media", self->priv->object_path); if (self->priv->remote_sending_state != FUTURE_SENDING_STATE_SENDING) { self->priv->remote_sending_state = FUTURE_SENDING_STATE_SENDING; g_hash_table_insert (updated_senders, GUINT_TO_POINTER (self->priv->handle), GUINT_TO_POINTER (FUTURE_SENDING_STATE_SENDING)); } } else { if (self->priv->remote_sending_state == FUTURE_SENDING_STATE_PENDING_SEND) { g_message ("%s: SIGNALLING: receive: No, I refuse to send you media", self->priv->object_path); self->priv->remote_sending_state = FUTURE_SENDING_STATE_NONE; g_hash_table_insert (updated_senders, GUINT_TO_POINTER (self->priv->handle), GUINT_TO_POINTER (FUTURE_SENDING_STATE_NONE)); } else if (self->priv->remote_sending_state == FUTURE_SENDING_STATE_SENDING) { g_message ("%s: SIGNALLING: receive: I will no longer send media", self->priv->object_path); self->priv->remote_sending_state = FUTURE_SENDING_STATE_NONE; g_hash_table_insert (updated_senders, GUINT_TO_POINTER (self->priv->handle), GUINT_TO_POINTER (FUTURE_SENDING_STATE_NONE)); } } if (g_hash_table_size (updated_senders) != 0) { GArray *removed_senders = g_array_sized_new (FALSE, FALSE, sizeof (guint), 0); future_svc_call_stream_emit_senders_changed (self, updated_senders, removed_senders); g_array_free (removed_senders, TRUE); } g_hash_table_unref (updated_senders); }
static void example_call_stream_change_direction (ExampleCallStream *self, gboolean want_to_send, gboolean want_to_receive) { GHashTable *updated_senders = g_hash_table_new (NULL, NULL); if (want_to_send) { if (self->priv->local_sending_state != FUTURE_SENDING_STATE_SENDING) { if (self->priv->local_sending_state == FUTURE_SENDING_STATE_PENDING_SEND) { g_message ("%s: SIGNALLING: send: I will now send you media", self->priv->object_path); } g_message ("%s: MEDIA: sending media to peer", self->priv->object_path); self->priv->local_sending_state = FUTURE_SENDING_STATE_SENDING; g_hash_table_insert (updated_senders, GUINT_TO_POINTER (tp_base_connection_get_self_handle ( self->priv->conn)), GUINT_TO_POINTER (FUTURE_SENDING_STATE_SENDING)); } } else { if (self->priv->local_sending_state == FUTURE_SENDING_STATE_SENDING) { g_message ("%s: SIGNALLING: send: I will no longer send you media", self->priv->object_path); g_message ("%s: MEDIA: no longer sending media to peer", self->priv->object_path); self->priv->local_sending_state = FUTURE_SENDING_STATE_NONE; g_hash_table_insert (updated_senders, GUINT_TO_POINTER (tp_base_connection_get_self_handle ( self->priv->conn)), GUINT_TO_POINTER (FUTURE_SENDING_STATE_NONE)); } else if (self->priv->local_sending_state == FUTURE_SENDING_STATE_PENDING_SEND) { g_message ("%s: SIGNALLING: send: refusing to send you media", self->priv->object_path); self->priv->local_sending_state = FUTURE_SENDING_STATE_NONE; g_hash_table_insert (updated_senders, GUINT_TO_POINTER (tp_base_connection_get_self_handle ( self->priv->conn)), GUINT_TO_POINTER (FUTURE_SENDING_STATE_NONE)); } } if (want_to_receive) { if (self->priv->remote_sending_state == FUTURE_SENDING_STATE_NONE) { g_message ("%s: SIGNALLING: send: send me media, please?", self->priv->object_path); self->priv->remote_sending_state = FUTURE_SENDING_STATE_PENDING_SEND; g_timeout_add_full (G_PRIORITY_DEFAULT, self->priv->simulation_delay, simulate_contact_agreed_to_send_cb, g_object_ref (self), g_object_unref); g_hash_table_insert (updated_senders, GUINT_TO_POINTER (self->priv->handle), GUINT_TO_POINTER (FUTURE_SENDING_STATE_PENDING_SEND)); } } else { if (self->priv->remote_sending_state != FUTURE_SENDING_STATE_NONE) { g_message ("%s: SIGNALLING: send: Please stop sending me media", self->priv->object_path); g_message ("%s: MEDIA: suppressing output of stream", self->priv->object_path); self->priv->remote_sending_state = FUTURE_SENDING_STATE_NONE; g_hash_table_insert (updated_senders, GUINT_TO_POINTER (self->priv->handle), GUINT_TO_POINTER (FUTURE_SENDING_STATE_NONE)); } } if (g_hash_table_size (updated_senders) != 0) { GArray *removed_senders = g_array_sized_new (FALSE, FALSE, sizeof (guint), 0); future_svc_call_stream_emit_senders_changed (self, updated_senders, removed_senders); g_array_free (removed_senders, TRUE); } g_hash_table_unref (updated_senders); }