static void
channel_get_all_properties_cb (TpProxy *proxy,
    GHashTable *properties,
    const GError *error,
    gpointer user_data,
    GObject *weak_object)
{
  CallbacksData *cb_data = user_data;
  EmpathyFTHandler *handler = EMPATHY_FT_HANDLER (weak_object);
  EmpathyFTHandlerPriv *priv = GET_PRIV (handler);
  TpHandle c_handle;

  if (error != NULL)
    {
      if (!g_cancellable_is_cancelled (priv->cancellable))
        g_cancellable_cancel (priv->cancellable);

      cb_data->callback (handler, (GError *) error, cb_data->user_data);

      callbacks_data_free (cb_data);
      return;
    }

  priv->total_bytes = g_value_get_uint64 (
      g_hash_table_lookup (properties, "Size"));

  priv->transferred_bytes = g_value_get_uint64 (
      g_hash_table_lookup (properties, "TransferredBytes"));

  priv->filename = g_value_dup_string (
      g_hash_table_lookup (properties, "Filename"));

  priv->content_hash = g_value_dup_string (
      g_hash_table_lookup (properties, "ContentHash"));

  priv->content_hash_type = g_value_get_uint (
      g_hash_table_lookup (properties, "ContentHashType"));

  priv->content_type = g_value_dup_string (
      g_hash_table_lookup (properties, "ContentType"));

  priv->description = g_value_dup_string (
      g_hash_table_lookup (properties, "Description"));

  c_handle = tp_channel_get_handle (TP_CHANNEL (proxy), NULL);
  empathy_tp_contact_factory_get_from_handle (
      tp_channel_borrow_connection (TP_CHANNEL (proxy)), c_handle,
      contact_factory_contact_cb, cb_data, callbacks_data_free,
      G_OBJECT (handler));
}
static void
handle_dbus_channel(TpSimpleHandler* /*handler*/,
	TpAccount* /*account*/,
	TpConnection* /*connection*/,
	GList* channels,
	GList* /*requests*/,
	gint64 /*user_action_time*/,
	TpHandleChannelsContext* context,
	gpointer user_data)
{
	UT_DEBUGMSG(("handle_dbus_channel()\n"));

	TelepathyAccountHandler* pHandler = reinterpret_cast<TelepathyAccountHandler*>(user_data);
	UT_return_if_fail(pHandler);

	for (GList* chan = channels; chan; chan = chan->next)
	{
		TpChannel* channel = TP_CHANNEL(chan->data);
		UT_continue_if_fail(channel);
		UT_DEBUGMSG((">>>>> incoming dbus channel: %s\n", tp_channel_get_identifier(channel)));

		if (tp_channel_get_channel_type_id(channel) != TP_IFACE_QUARK_CHANNEL_TYPE_DBUS_TUBE)
			continue;

		/* accept the channel */
		tp_cli_channel_type_dbus_tube_call_accept(channel, -1,
					TP_SOCKET_ACCESS_CONTROL_LOCALHOST,
					tube_accept_cb, user_data, NULL, NULL);
	}

	tp_handle_channels_context_accept(context);
}
Example #3
0
static void
ft_transfer_state_cb (TpFileTransferChannel *channel,
    GParamSpec *pspec,
    EmpathyFTHandler *handler)
{
  EmpathyFTHandlerPriv *priv = handler->priv;
  TpFileTransferStateChangeReason reason;
  TpFileTransferState state = tp_file_transfer_channel_get_state (
      channel, &reason);

  (void)pspec;      /* suppress unused-parameter warning */

  if (state == TP_FILE_TRANSFER_STATE_COMPLETED)
    {
      priv->is_completed = TRUE;
      g_signal_emit (handler, signals[TRANSFER_DONE], 0, channel);

      tp_channel_close_async (TP_CHANNEL (channel), NULL, NULL);

      if (empathy_ft_handler_is_incoming (handler) && priv->use_hash)
        {
          check_hash_incoming (handler);
        }
    }
  else if (state == TP_FILE_TRANSFER_STATE_CANCELLED)
    {
      GError *error = error_from_state_change_reason (reason);
      emit_error_signal (handler, error);
      g_clear_error (&error);
    }
}
Example #4
0
static void
on_call_state_changed_cb (TpCallChannel *call,
  TpCallState state,
  TpCallFlags flags,
  TpCallStateReason *reason,
  GHashTable *details,
  EmpathyCallHandler *handler)
{
  EmpathyCallHandlerPriv *priv = handler->priv;

  /* Clean up the TfChannel before bubbling the state-change signal
   * further up. This ensures that the conference-removed signal is
   * emitted before state-changed so that the client gets a chance
   * to remove the conference from the pipeline before resetting the
   * pipeline itself.
   */
  if (state == TP_CALL_STATE_ENDED)
    {
      tp_channel_close_async (TP_CHANNEL (call), NULL, NULL);
      priv->accept_when_initialised = FALSE;
      tp_clear_object (&priv->call);
      tp_clear_object (&priv->tfchannel);
    }

  g_signal_emit (handler, signals[STATE_CHANGED], 0, state,
      reason->dbus_reason);

  if (state == TP_CALL_STATE_INITIALISED &&
      priv->accept_when_initialised)
    {
      tp_call_channel_accept_async (priv->call, on_call_accepted_cb, NULL);
      priv->accept_when_initialised = FALSE;
    }
}
static void
_offer_with_address (TpStreamTubeChannel *self,
    GHashTable *params)
{
  GValue *addressv = NULL;
  GError *error = NULL;

  addressv = tp_address_variant_from_g_socket_address (self->priv->address,
      &self->priv->socket_type, &error);
  if (error != NULL)
    {
      operation_failed (self, error);

      g_clear_error (&error);
      goto finally;
    }

  /* Connect the NewRemoteConnection signal */
  tp_cli_channel_type_stream_tube_connect_to_new_remote_connection (
      TP_CHANNEL (self), _new_remote_connection,
      NULL, NULL, G_OBJECT (self), &error);
  if (error != NULL)
    {
      operation_failed (self, error);

      g_clear_error (&error);
      goto finally;
    }

  g_assert (self->priv->parameters == NULL);
  if (params != NULL)
    self->priv->parameters = g_hash_table_ref (params);
  else
    self->priv->parameters = tp_asv_new (NULL, NULL);

  g_object_notify (G_OBJECT (self), "parameters");
  g_object_notify (G_OBJECT (self), "parameters-vardict");

  /* Call Offer */
  tp_cli_channel_type_stream_tube_call_offer (TP_CHANNEL (self), -1,
      self->priv->socket_type, addressv, self->priv->access_control,
      self->priv->parameters, _channel_offered, NULL, NULL, G_OBJECT (self));

finally:
  if (addressv != NULL)
    tp_g_value_slice_free (addressv);
}
Example #6
0
static void
empathy_call_handler_start_tpfs (EmpathyCallHandler *self)
{
  EmpathyCallHandlerPriv *priv = GET_PRIV (self);

  tf_channel_new_async (TP_CHANNEL (priv->call),
      on_tf_channel_ready, self);
}
/**
 * tp_stream_tube_channel_get_service:
 * @self: a #TpStreamTubeChannel
 *
 * Return the #TpStreamTubeChannel:service property
 *
 * Returns: (transfer none): the value of #TpStreamTubeChannel:service
 *
 * Since: 0.13.2
 */
const gchar *
tp_stream_tube_channel_get_service (TpStreamTubeChannel *self)
{
  GHashTable *props;

  props = _tp_channel_get_immutable_properties (TP_CHANNEL (self));

  return tp_asv_get_string (props, TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE);
}
Example #8
0
static void
channel_prepared_cb (
    GObject *source,
    GAsyncResult *result,
    gpointer user_data)
{
  TpFileTransferChannel *channel = TP_FILE_TRANSFER_CHANNEL (source);
  CallbacksData *cb_data = user_data;
  EmpathyFTHandler *handler = cb_data->handler;
  EmpathyFTHandlerPriv *priv = handler->priv;
  GHashTable *properties;
  GError *error = NULL;

  if (!tp_proxy_prepare_finish (channel, result, &error))
    {
      if (!g_cancellable_is_cancelled (priv->cancellable))
        g_cancellable_cancel (priv->cancellable);

      cb_data->callback (handler, error, cb_data->user_data);
      g_clear_error (&error);
      callbacks_data_free (cb_data);
      return;
    }
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  properties = tp_channel_borrow_immutable_properties (TP_CHANNEL (channel));
  #pragma GCC diagnostic pop

  priv->content_hash = g_strdup (
      tp_asv_get_string (properties, "ContentHash"));

  priv->content_hash_type = tp_asv_get_uint32 (
      properties, "ContentHashType", NULL);

  priv->contact = g_object_ref (tp_channel_get_target_contact (TP_CHANNEL (channel)));

  cb_data->callback (handler, NULL, cb_data->user_data);
}
static void
new_local_connection_identified (TpStreamTubeChannel *self,
    GSocketConnection *conn,
    guint connection_id)
{
  TpHandle initiator_handle;
  TpStreamTubeConnection *tube_conn;
  TpConnection *connection;
  GArray *features;

  tube_conn = _tp_stream_tube_connection_new (conn, self);

  g_hash_table_insert (self->priv->tube_connections,
      GUINT_TO_POINTER (connection_id), tube_conn);

  g_object_weak_ref (G_OBJECT (tube_conn), remote_connection_destroyed_cb,
      self);

  /* We are accepting a tube so the contact of the connection is the
   * initiator of the tube */
  G_GNUC_BEGIN_IGNORE_DEPRECATIONS
  initiator_handle = tp_channel_get_initiator_handle (TP_CHANNEL (self));

  connection = tp_channel_get_connection (TP_CHANNEL (self));
  features = tp_simple_client_factory_dup_contact_features (
      tp_proxy_get_factory (connection), connection);

  /* Pass ownership of tube_conn to the function */
  tp_connection_get_contacts_by_handle (connection,
      1, &initiator_handle,
      features->len, (TpContactFeature *) features->data,
      new_local_connection_with_contact,
      tube_conn, g_object_unref, G_OBJECT (self));
  G_GNUC_END_IGNORE_DEPRECATIONS

  g_array_unref (features);
}
Example #10
0
void
empathy_call_handler_start_call (EmpathyCallHandler *handler,
    gint64 timestamp)
{
  EmpathyCallHandlerPriv *priv = GET_PRIV (handler);
  TpAccountChannelRequest *req;
  TpAccount *account;
  GHashTable *request;

  if (priv->call != NULL)
    {
      empathy_call_handler_start_tpfs (handler);

      if (tp_channel_get_requested (TP_CHANNEL (priv->call)))
        {
          /* accept outgoing channels immediately */
          tp_call_channel_accept_async (priv->call,
              on_call_accepted_cb, NULL);
        }
      else
        {
          /* accepting incoming channels when they are INITIALISED */
          if (tp_call_channel_get_state (priv->call, NULL, NULL, NULL) ==
              TP_CALL_STATE_INITIALISED)
            tp_call_channel_accept_async (priv->call,
                on_call_accepted_cb, NULL);
          else
            priv->accept_when_initialised = TRUE;
        }

      return;
    }

  /* No TpCallChannel (we are redialing). Request a new call channel */
  g_assert (priv->contact != NULL);

  account = empathy_contact_get_account (priv->contact);
  request = empathy_call_create_call_request (
      empathy_contact_get_id (priv->contact),
      priv->initial_audio, priv->initial_video);

  req = tp_account_channel_request_new (account, request, timestamp);

  tp_account_channel_request_create_and_handle_channel_async (req, NULL,
      empathy_call_handler_request_cb, handler);

  g_object_unref (req);
  g_hash_table_unref (request);
}
Example #11
0
static void
join_cb (GObject *source,
    GAsyncResult *result,
    gpointer user_data)
{
  TpChannel *channel = TP_CHANNEL (source);
  GError *error = NULL;

  if (!tp_channel_join_finish (channel, result, &error))
    {
      DEBUG ("Failed to join chat (%s): %s",
          tp_channel_get_identifier (channel), error->message);
      g_error_free (error);
    }
}
Example #12
0
/**
 * empathy_ft_handler_cancel_transfer:
 * @handler: an #EmpathyFTHandler
 *
 * Cancels an ongoing handler operation. Note that this doesn't destroy
 * the object, which will keep all the properties, altough it won't be able
 * to do any more I/O.
 */
void
empathy_ft_handler_cancel_transfer (EmpathyFTHandler *handler)
{
  EmpathyFTHandlerPriv *priv;

  g_return_if_fail (EMPATHY_IS_FT_HANDLER (handler));

  priv = handler->priv;

  /* if we don't have a channel, we are hashing, so
   * we can just cancel the GCancellable to stop it.
   */
  if (priv->channel == NULL)
    g_cancellable_cancel (priv->cancellable);
  else
    tp_channel_close_async (TP_CHANNEL (priv->channel), NULL, NULL);
}
static void
on_channel_close_returned (GObject *source,
    GAsyncResult *result,
    gpointer user_data)
{
  TpChannel *channel = TP_CHANNEL (user_data);
  GError *error = NULL;

  tp_channel_close_finish (channel, result, &error);
  if (error != NULL)
    {
      DEBUG ("Channel.Close() failed: %s", error->message);
      g_clear_error (&error);
    }

  g_object_unref (channel);
}
Example #14
0
static void
do_dispose (GObject *object)
{
  EmpathyFTHandler *self = EMPATHY_FT_HANDLER (object);
  EmpathyFTHandlerPriv *priv = self->priv;

  if (priv->dispose_run)
    return;

  priv->dispose_run = TRUE;

  if (priv->account != NULL) {
    g_object_unref (priv->account);
    priv->account = NULL;
  }

  if (priv->contact != NULL) {
    g_object_unref (priv->contact);
    priv->contact = NULL;
  }

  if (priv->gfile != NULL) {
    g_object_unref (priv->gfile);
    priv->gfile = NULL;
  }

  if (priv->channel != NULL) {
    tp_channel_close_async (TP_CHANNEL (priv->channel), NULL, NULL);
    g_object_unref (priv->channel);
    priv->channel = NULL;
  }

  if (priv->cancellable != NULL) {
    g_object_unref (priv->cancellable);
    priv->cancellable = NULL;
  }

  if (priv->request != NULL)
    {
      g_hash_table_unref (priv->request);
      priv->request = NULL;
    }

  G_OBJECT_CLASS (empathy_ft_handler_parent_class)->dispose (object);
}
static void
connection_identified (TpStreamTubeChannel *self,
    GSocketConnection *conn,
    TpHandle handle,
    guint connection_id)
{
  TpStreamTubeConnection *tube_conn;

  tube_conn = _tp_stream_tube_connection_new (conn, self);

  g_hash_table_insert (self->priv->tube_connections,
      GUINT_TO_POINTER (connection_id), tube_conn);

  g_object_weak_ref (G_OBJECT (tube_conn), remote_connection_destroyed_cb,
      self);

  if (can_identify_contact (self))
    {
      TpConnection *connection;
      GArray *features;

      connection = tp_channel_get_connection (TP_CHANNEL (self));
      features = tp_simple_client_factory_dup_contact_features (
          tp_proxy_get_factory (connection), connection);

      /* Spec does not give the id with the handle */
      G_GNUC_BEGIN_IGNORE_DEPRECATIONS
      /* Pass the ref on tube_conn to the function */
      tp_connection_get_contacts_by_handle (connection,
          1, &handle,
          features->len, (TpContactFeature *) features->data,
          _new_remote_connection_with_contact,
          tube_conn, g_object_unref, G_OBJECT (self));
       G_GNUC_END_IGNORE_DEPRECATIONS

      g_array_unref (features);
    }
  else
    {
      g_signal_emit (self, _signals[INCOMING], 0, tube_conn);

      g_object_unref (tube_conn);
    }
}
static TpChannel *
create_channel (TpSimpleClientFactory  *self,
		TpConnection           *conn,
		const gchar            *object_path,
		const GHashTable       *properties,
		GError                **error)
{
	const gchar *channel_type;

	channel_type = tp_asv_get_string (properties, TP_PROP_CHANNEL_CHANNEL_TYPE);

	if (g_strcmp0 (channel_type, TP_IFACE_CHANNEL_TYPE_TEXT) == 0) {
		return TP_CHANNEL (tmc_text_channel_new (self, conn, object_path, properties, error));
	} else {
		g_debug ("Unknown channel type: %s", channel_type);

		return TP_SIMPLE_CLIENT_FACTORY_CLASS (tmc_client_factory_parent_class)->create_channel (self, conn, object_path, properties, error);
	}
}
static gboolean
can_identify_contact (TpStreamTubeChannel *self)
{
  TpHandleType handle_type;

  tp_channel_get_handle (TP_CHANNEL (self), &handle_type);

  /* With contact stream tube, it's always the same contact connecting to the
   * tube */
  if (handle_type == TP_HANDLE_TYPE_CONTACT)
    return TRUE;

  /* Room stream tube, we need either the Credentials or Port access control
   * to properly identify connections. */
  if (self->priv->access_control == TP_SOCKET_ACCESS_CONTROL_CREDENTIALS ||
      self->priv->access_control == TP_SOCKET_ACCESS_CONTROL_PORT)
    return TRUE;

  return FALSE;
}
static gboolean
has_ongoing_calls (EmpathyCallObserver *self)
{
  GList *l;

  for (l = self->priv->channels; l != NULL; l = l->next)
    {
      TpChannel *channel = TP_CHANNEL (l->data);
      GQuark type = tp_channel_get_channel_type_id (channel);

      /* Check that Call channels are not ended */
      if (type == TP_IFACE_QUARK_CHANNEL_TYPE_CALL &&
          tp_call_channel_get_state (TP_CALL_CHANNEL (channel),
              NULL, NULL, NULL) == TP_CALL_STATE_ENDED)
        continue;

      return TRUE;
    }

  return FALSE;
}
static void
on_channel_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
{
    TpChannel *tp_chan = TP_CHANNEL (source_object);
    McdChannel *channel, **channel_ptr = user_data;
    McdChannelPrivate *priv;
    gboolean requested, valid;
    GError *error = NULL;

    if (!tp_proxy_prepare_finish (tp_chan, result, &error))
    {
        DEBUG ("failed to prepare channel: %s", error->message);
        g_clear_error (&error);
        return;
    }

    channel = *channel_ptr;
    if (channel)
	g_object_remove_weak_pointer ((GObject *)channel,
				      (gpointer)channel_ptr);
    g_slice_free (McdChannel *, channel_ptr);
    if (error)
    {
        DEBUG ("got error: %s", error->message);
	return;
    }

    if (!channel) return;

    DEBUG ("channel %p is ready", channel);
    priv = channel->priv;
    requested = tp_asv_get_boolean
        (tp_channel_borrow_immutable_properties (tp_chan),
         TP_IFACE_CHANNEL ".Requested", &valid);
    if (valid)
        priv->outgoing = requested;
}
static void
mex_telepathy_channel_set_property (GObject      *object,
                                    guint         property_id,
                                    const GValue *value,
                                    GParamSpec   *pspec)
{
  MexTelepathyChannel *self = MEX_TELEPATHY_CHANNEL (object);
  MexTelepathyChannelPrivate *priv = self->priv;

  switch (property_id)
    {
    case PROP_CHANNEL:
      priv->channel = TP_CHANNEL (g_value_get_object (value));
      mex_telepathy_channel_initialize_channel(self);
      break;

    case PROP_CONNECTION:
      priv->connection = TP_CONNECTION (g_value_get_object (value));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
    }
}
static void
mex_telepathy_channel_on_content_added (TfChannel *channel,
                                        TfContent *content,
                                        gpointer   user_data)
{
  MexTelepathyChannel *self = MEX_TELEPATHY_CHANNEL (user_data);
  MexTelepathyChannelPrivate *priv = self->priv;
  GstPad *srcpad, *sinkpad;
  FsMediaType mtype;
  GstElement *element;
  GstStateChangeReturn ret;

  MEX_DEBUG ("Content added");

  g_object_get (content,
                "sink-pad", &sinkpad,
                "media-type", &mtype,
                NULL);

  switch (mtype)
    {
    case FS_MEDIA_TYPE_AUDIO:
      MEX_DEBUG ("Audio content added");
      element = gst_parse_bin_from_description (
        "autoaudiosrc ! audioresample ! audioconvert ! volume name=micvolume", TRUE, NULL);
      priv->outgoing_mic = element;
      priv->mic_volume = gst_bin_get_by_name (GST_BIN (priv->outgoing_mic), "micvolume");
      break;
    case FS_MEDIA_TYPE_VIDEO:
      MEX_DEBUG ("Video content added");
      element = mex_telepathy_channel_setup_video_source (self, content);
      break;
    default:
      MEX_WARNING ("Unknown media type");
      g_object_unref (sinkpad);
      return;
    }

  g_signal_connect (content, "src-pad-added",
                    G_CALLBACK (mex_telepathy_channel_on_src_pad_added), self);

  gst_bin_add (GST_BIN (priv->pipeline), element);
  srcpad = gst_element_get_pad (element, "src");

  if (GST_PAD_LINK_FAILED (gst_pad_link (srcpad, sinkpad)))
    {
      tp_channel_close_async (TP_CHANNEL (priv->channel), NULL, NULL);
      MEX_WARNING ("Couldn't link source pipeline !?");
      return;
    }

  ret = gst_element_set_state (element, GST_STATE_PLAYING);
  if (ret == GST_STATE_CHANGE_FAILURE)
    {
      tp_channel_close_async (TP_CHANNEL (priv->channel), NULL, NULL);
      MEX_WARNING ("source pipeline failed to start!?");
      return;
    }

  g_object_unref (srcpad);
  g_object_unref (sinkpad);
}
static void
mex_telepathy_channel_on_src_pad_added (TfContent *content,
                                        TpHandle   handle,
                                        FsStream  *stream,
                                        GstPad    *pad,
                                        FsCodec   *codec,
                                        gpointer   user_data)
{
  MexTelepathyChannel *self = MEX_TELEPATHY_CHANNEL (user_data);
  MexTelepathyChannelPrivate *priv = self->priv;

  gchar *cstr = fs_codec_to_string (codec);
  FsMediaType mtype;
  GstPad *sinkpad;
  GstElement *element;
  GstStateChangeReturn ret;

  /* Upon pad added, clear the "in progress" box+padding */
  clutter_actor_hide (CLUTTER_ACTOR (priv->busy_box));
  clutter_actor_show (CLUTTER_ACTOR (priv->full_frame) );

  MEX_DEBUG ("New src pad: %s", cstr);
  g_object_get (content, "media-type", &mtype, NULL);

  switch (mtype)
    {
    case FS_MEDIA_TYPE_AUDIO:
      element = gst_parse_bin_from_description (
        "audioconvert ! audioresample ! audioconvert ! autoaudiosink",
        TRUE, NULL);
      break;
    case FS_MEDIA_TYPE_VIDEO:
      element = priv->incoming_sink;
      break;
    default:
      MEX_WARNING ("Unknown media type");
      return;
    }

  if (!gst_bin_add (GST_BIN (priv->pipeline), element))
    {
      MEX_WARNING ("Failed to add sink element to pipeline");
    }
  sinkpad = gst_element_get_pad (element, "sink");
  ret = gst_element_set_state (element, GST_STATE_PLAYING);
  if (ret == GST_STATE_CHANGE_FAILURE)
    {
      tp_channel_close_async (TP_CHANNEL (priv->channel), NULL, NULL);
      MEX_WARNING ("Failed to start tee sink pipeline !?");
      return;
    }

  if (GST_PAD_LINK_FAILED (gst_pad_link (pad, sinkpad)))
    {
      tp_channel_close_async (TP_CHANNEL (priv->channel), NULL, NULL);
      MEX_WARNING ("Couldn't link sink pipeline !?");
      return;
    }

  g_object_unref (sinkpad);

  /* Start in FULL mode */
  mex_telepathy_channel_set_tool_mode (self, TOOL_MODE_FULL, 100);
}
static void
mex_telepathy_channel_initialize_channel (MexTelepathyChannel *self)
{
  MexTelepathyChannelPrivate *priv = self->priv;

  GstBus *bus;
  GstElement *pipeline;
  GstStateChangeReturn ret;
  gboolean ready;

  TpHandle contactHandle = tp_channel_get_handle (priv->channel, NULL);
  TpContactFeature features[] = { TP_CONTACT_FEATURE_ALIAS,
                                  TP_CONTACT_FEATURE_AVATAR_DATA,
                                  TP_CONTACT_FEATURE_AVATAR_TOKEN};

  MEX_INFO ("New channel");

  if (contactHandle)
    tp_connection_get_contacts_by_handle (
      priv->connection, 1, &contactHandle, 1,
      features,
      mex_telepathy_channel_on_contact_fetched,
      self, NULL, NULL);

  pipeline = gst_pipeline_new (NULL);

  ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);

  if (ret == GST_STATE_CHANGE_FAILURE)
    {
      tp_channel_close_async (TP_CHANNEL (priv->channel), NULL, NULL);
      g_object_unref (pipeline);
      MEX_WARNING ("Failed to start an empty pipeline !?");
      return;
    }

  priv->pipeline = pipeline;

  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
  priv->buswatch = gst_bus_add_watch (bus, mex_telepathy_channel_on_bus_watch,
                                      self);
  g_object_unref (bus);

  tf_channel_new_async (priv->channel, mex_telepathy_channel_new_tf_channel,
                        self);

  tpy_cli_channel_type_call_call_accept (TP_PROXY (priv->channel), -1,
                                         NULL, NULL, NULL, NULL);

  priv->channel = g_object_ref (priv->channel);
  g_signal_connect (priv->channel, "notify::ready",
                    G_CALLBACK (mex_telepathy_channel_on_ready),
                    self);
  g_signal_connect (priv->channel, "invalidated",
                    G_CALLBACK (mex_telepathy_channel_on_proxy_invalidated),
                    self);

  g_signal_connect (TPY_CALL_CHANNEL (priv->channel), "state-changed",
                    G_CALLBACK (mex_telepathy_channel_on_call_state_changed),
                    self);

  g_object_get (priv->channel, "ready", &ready, NULL);
  if (ready)
    mex_telepathy_channel_on_ready (TPY_CALL_CHANNEL (priv->channel), NULL, self);
}
Example #24
0
static void
process_tp_chat (EmpathyChatManager *self,
    EmpathyTpChat *tp_chat,
    TpAccount *account,
    gint64 user_action_time)
{
  EmpathyChatManagerPriv *priv = GET_PRIV (self);
  EmpathyChat *chat = NULL;
  const gchar *id;
  EmpathyChatWindow *window;

  id = empathy_tp_chat_get_id (tp_chat);
  if (!tp_str_empty (id))
    {
      chat = empathy_chat_window_find_chat (account, id,
          tp_text_channel_is_sms_channel ((TpTextChannel *) tp_chat));
    }

  if (chat != NULL)
    {
      empathy_chat_set_tp_chat (chat, tp_chat);
    }
  else
    {
      GHashTable *chats = NULL;

      chat = empathy_chat_new (tp_chat);
      /* empathy_chat_new returns a floating reference as EmpathyChat is
       * a GtkWidget. This reference will be taken by a container
       * (a GtkNotebook) when we'll call empathy_chat_window_present_chat */

      priv->num_displayed_chat++;

      DEBUG ("Chat displayed; we are now displaying %u chat",
          priv->num_displayed_chat);

      g_signal_emit (self, signals[DISPLAYED_CHATS_CHANGED], 0,
          priv->num_displayed_chat);

      /* Set the saved message in the channel if we have one. */
      chats = g_hash_table_lookup (priv->messages,
          tp_proxy_get_object_path (account));

      if (chats != NULL)
        {
          const gchar *msg = g_hash_table_lookup (chats, id);

          if (msg != NULL)
            empathy_chat_set_text (chat, msg);
        }

      g_object_weak_ref ((GObject *) chat, chat_destroyed_cb, self);
    }

  window = empathy_chat_window_present_chat (chat, user_action_time);

  if (priv->individual_mgr == NULL)
    {
      /* We want to cache it as soon it's created */
      tp_g_signal_connect_object (window, "notify::individual-manager",
        G_CALLBACK (individual_mgr_cb), self, 0);
    }

  if (empathy_tp_chat_is_invited (tp_chat, NULL))
    {
      /* We have been invited to the room. Add ourself as member as this
       * channel has been approved. */
      tp_channel_join_async (TP_CHANNEL (tp_chat), "", join_cb, self);
    }
}
Example #25
0
File: msg.c Project: keis/charlatan
static void
channel_ready (GObject      *source,
               GAsyncResult *result,
               gpointer      user_data)
{
    ChVisitor *visitor = (ChVisitor*) user_data;
    TpChannel *channel;
    const gchar *ident;
    TpMessage *message;

    GError *error = NULL;
    if (!tp_proxy_prepare_finish (source, result, &error)) {
        g_printerr ("error loading channel: %s\n", error->message);
        return;
    }

    channel = TP_CHANNEL (source);
    ident = tp_channel_get_identifier (channel);

    if (verbose > 0) {
        g_printerr ("channel ready \"%s\" (type %s)\n",
                    ident,
                    tp_channel_get_channel_type (channel));
    }

    GList *messages, *iter;
    if (TP_IS_TEXT_CHANNEL (channel)) {
        messages = tp_text_channel_dup_pending_messages (
             TP_TEXT_CHANNEL (channel));

        for (iter = messages; iter; iter = iter->next) {
            TpMessage *message = TP_MESSAGE (iter->data);
            message_cb (message);
        }

        if (acknowledge) {
            tp_text_channel_ack_messages_async (TP_TEXT_CHANNEL (channel),
                                                messages,
                                                ack_messages_cb,
                                                NULL);
        }

        g_list_free_full (messages, g_object_unref);

        if (send_message && !has_sent_message_to (ident)) {
            message = tp_client_message_new_text(0, msg_buffer);
            g_ptr_array_add (messages_sent, g_strdup (ident));
            ch_visitor_incref (visitor);
            tp_text_channel_send_message_async (TP_TEXT_CHANNEL (channel),
                                                message,
                                                0,
                                                send_message_cb,
                                                visitor);
        }
    } else {
        g_printerr ("error loading channel: %s is not a text channel\n",
                    tp_channel_get_identifier (channel));
    }

    ch_visitor_decref (visitor);
}
static void
tp_stream_tube_channel_constructed (GObject *obj)
{
  TpStreamTubeChannel *self = (TpStreamTubeChannel *) obj;
  void (*chain_up) (GObject *) =
    ((GObjectClass *) tp_stream_tube_channel_parent_class)->constructed;
  TpChannel *chan = (TpChannel *) obj;
  GHashTable *props;
  GError *err = NULL;

  if (chain_up != NULL)
    chain_up (obj);

  if (tp_channel_get_channel_type_id (chan) !=
      TP_IFACE_QUARK_CHANNEL_TYPE_STREAM_TUBE)
    {
      GError error = { TP_DBUS_ERRORS, TP_DBUS_ERROR_INCONSISTENT,
          "Channel is not a stream tube" };

      DEBUG ("Channel is not a stream tube: %s", tp_channel_get_channel_type (
            chan));

      tp_proxy_invalidate (TP_PROXY (self), &error);
      return;
    }

  props = _tp_channel_get_immutable_properties (TP_CHANNEL (self));

  if (tp_asv_get_string (props, TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE)
      == NULL)
    {
      GError error = { TP_DBUS_ERRORS, TP_DBUS_ERROR_INCONSISTENT,
          "Tube doesn't have StreamTube.Service property" };

      DEBUG ("%s", error.message);

      tp_proxy_invalidate (TP_PROXY (self), &error);
      return;
    }

   /*  Tube.Parameters is immutable for incoming tubes. For outgoing ones,
    *  it's defined when offering the tube. */
  if (!tp_channel_get_requested (TP_CHANNEL (self)))
    {
      GHashTable *params;

      params = tp_asv_get_boxed (props,
          TP_PROP_CHANNEL_INTERFACE_TUBE_PARAMETERS,
          TP_HASH_TYPE_STRING_VARIANT_MAP);

      if (params == NULL)
        {
          DEBUG ("Incoming tube doesn't have Tube.Parameters property");

          self->priv->parameters = tp_asv_new (NULL, NULL);
        }
      else
        {
          self->priv->parameters = g_boxed_copy (
              TP_HASH_TYPE_STRING_VARIANT_MAP, params);
        }
    }

  tp_cli_channel_type_stream_tube_connect_to_connection_closed (
      TP_CHANNEL (self), connection_closed_cb, NULL, NULL,
      G_OBJECT (self), &err);

  if (err != NULL)
    {
      DEBUG ("Failed to connect to ConnectionClosed signal: %s",
          err->message);

      g_error_free (err);
    }
}
static void
_channel_accepted (TpChannel *channel,
    const GValue *addressv,
    const GError *in_error,
    gpointer user_data,
    GObject *obj)
{
  TpStreamTubeChannel *self = (TpStreamTubeChannel *) obj;
  GSocketAddress *remote_address;
  GError *error = NULL;

  if (in_error != NULL)
    {
      DEBUG ("Failed to Accept Stream Tube: %s", in_error->message);

      operation_failed (self, in_error);
      return;
    }

  tp_cli_channel_type_stream_tube_connect_to_new_local_connection (
      TP_CHANNEL (self), new_local_connection_cb, NULL, NULL,
      G_OBJECT (self), &error);

  if (error != NULL)
    {
      DEBUG ("Failed to connect to NewLocalConnection signal");
      operation_failed (self, error);

      g_error_free (error);
      return;
    }

  remote_address = tp_g_socket_address_from_variant (self->priv->socket_type,
      addressv, &error);
  if (error != NULL)
    {
      DEBUG ("Failed to convert address: %s", error->message);

      operation_failed (self, error);
      g_error_free (error);
      return;
    }

  /* Connect to CM */
  g_socket_set_blocking (self->priv->client_socket, FALSE);
  g_socket_connect (self->priv->client_socket, remote_address, NULL, &error);

  if (error == NULL)
    {
      /* Socket is connected */
      client_socket_connected (self);
      goto out;
    }
  else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING))
    {
      /* We have to wait that the socket is connected */
      GSource *source;

      source = g_socket_create_source (self->priv->client_socket,
          G_IO_OUT, NULL);

      g_source_attach (source, g_main_context_get_thread_default ());

      g_source_set_callback (source, (GSourceFunc) client_socket_cb,
          self, NULL);

      g_error_free (error);
      g_source_unref (source);
    }
  else
    {
      DEBUG ("Failed to connect to CM: %s", error->message);

      operation_failed (self, error);

      g_error_free (error);
    }

out:
  g_object_unref (remote_address);
}
/**
 * tp_stream_tube_channel_offer_async:
 * @self: an outgoing #TpStreamTubeChannel
 * @params: (allow-none) (transfer none): parameters of the tube, or %NULL
 * @callback: a callback to call when the tube has been offered
 * @user_data: data to pass to @callback
 *
 * Offer an outgoing stream tube. When the tube has been offered, @callback
 * will be called. You can then call tp_stream_tube_channel_offer_finish()
 * to get the result of the operation.
 *
 * You have to connect to the #TpStreamTubeChannel::incoming signal to get a
 * #TpStreamTubeConnection each time a contact establishes a connection to
 * the tube.
 *
 * Since: 0.13.2
 */
void
tp_stream_tube_channel_offer_async (TpStreamTubeChannel *self,
    GHashTable *params,
    GAsyncReadyCallback callback,
    gpointer user_data)
{
  GHashTable *properties;
  GHashTable *supported_sockets;
  GError *error = NULL;

  g_return_if_fail (TP_IS_STREAM_TUBE_CHANNEL (self));
  g_return_if_fail (self->priv->result == NULL);
  g_return_if_fail (tp_channel_get_requested (TP_CHANNEL (self)));

  if (self->priv->service != NULL)
    {
      g_critical ("Can't reoffer Tube!");
      return;
    }

  self->priv->result = g_simple_async_result_new (G_OBJECT (self), callback,
      user_data, tp_stream_tube_channel_offer_async);

  properties = _tp_channel_get_immutable_properties (TP_CHANNEL (self));
  supported_sockets = tp_asv_get_boxed (properties,
      TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SUPPORTED_SOCKET_TYPES,
      TP_HASH_TYPE_SUPPORTED_SOCKET_MAP);

  if (!_tp_set_socket_address_type_and_access_control_type (supported_sockets,
      &self->priv->socket_type, &self->priv->access_control, &error))
    {
      operation_failed (self, error);

      g_clear_error (&error);
      return;
    }

  DEBUG ("Using socket type %u with access control %u", self->priv->socket_type,
      self->priv->access_control);

  self->priv->service = g_socket_service_new ();

  switch (self->priv->socket_type)
    {
#ifdef HAVE_GIO_UNIX
      case TP_SOCKET_ADDRESS_TYPE_UNIX:
        {
          self->priv->address = _tp_create_temp_unix_socket (
              self->priv->service, &error);

          /* check there wasn't an error on the final attempt */
          if (self->priv->address == NULL)
            {
              operation_failed (self, error);

              g_clear_error (&error);
              return;
            }
        }

        break;
#endif /* HAVE_GIO_UNIX */

      case TP_SOCKET_ADDRESS_TYPE_IPV4:
      case TP_SOCKET_ADDRESS_TYPE_IPV6:
        {
          GInetAddress *localhost;
          GSocketAddress *in_address;

          localhost = g_inet_address_new_loopback (
              self->priv->socket_type == TP_SOCKET_ADDRESS_TYPE_IPV4 ?
              G_SOCKET_FAMILY_IPV4 : G_SOCKET_FAMILY_IPV6);
          in_address = g_inet_socket_address_new (localhost, 0);

          g_socket_listener_add_address (
              G_SOCKET_LISTENER (self->priv->service), in_address,
              G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT,
              NULL, &self->priv->address, &error);

          g_object_unref (localhost);
          g_object_unref (in_address);

          if (error != NULL)
            {
              operation_failed (self, error);

              g_clear_error (&error);
              return;
            }

          break;
        }

      default:
        /* should have already errored */
        g_assert_not_reached ();
        break;
    }

  tp_g_signal_connect_object (self->priv->service, "incoming",
      G_CALLBACK (service_incoming_cb), self, 0);

  g_socket_service_start (self->priv->service);

  _offer_with_address (self, params);
}
/**
 * tp_stream_tube_channel_accept_async:
 * @self: an incoming #TpStreamTubeChannel
 * @callback: a callback to call when the tube has been accepted
 * @user_data: data to pass to @callback
 *
 * Accept an incoming stream tube. When the tube has been accepted, @callback
 * will be called. You can then call tp_stream_tube_channel_accept_finish()
 * to get a #TpStreamTubeConnection connected to the tube.
 *
 * Since: 0.13.2
 */
void
tp_stream_tube_channel_accept_async (TpStreamTubeChannel *self,
    GAsyncReadyCallback callback,
    gpointer user_data)
{
  GHashTable *properties;
  GHashTable *supported_sockets;
  GError *error = NULL;

  g_return_if_fail (TP_IS_STREAM_TUBE_CHANNEL (self));
  g_return_if_fail (self->priv->result == NULL);

  if (self->priv->access_control_param != NULL)
    {
      g_simple_async_report_error_in_idle (G_OBJECT (self), callback, user_data,
          TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Tube has already be accepted");

      return;
    }

  self->priv->result = g_simple_async_result_new (G_OBJECT (self), callback,
      user_data, tp_stream_tube_channel_accept_async);

  properties = _tp_channel_get_immutable_properties (TP_CHANNEL (self));
  supported_sockets = tp_asv_get_boxed (properties,
      TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SUPPORTED_SOCKET_TYPES,
      TP_HASH_TYPE_SUPPORTED_SOCKET_MAP);

  if (!_tp_set_socket_address_type_and_access_control_type (supported_sockets,
      &self->priv->socket_type, &self->priv->access_control, &error))
    {
      operation_failed (self, error);

      g_clear_error (&error);
      return;
    }

  DEBUG ("Using socket type %u with access control %u", self->priv->socket_type,
      self->priv->access_control);

  self->priv->client_socket = _tp_create_client_socket (self->priv->socket_type,
      &error);

  if (error != NULL)
    {
      DEBUG ("Failed to create socket: %s", error->message);

      operation_failed (self, error);
      g_clear_error (&error);
      return;
    }

  switch (self->priv->access_control)
    {
      case TP_SOCKET_ACCESS_CONTROL_LOCALHOST:
        /* Put a dummy value */
        self->priv->access_control_param = tp_g_value_slice_new_uint (0);
        break;

      case TP_SOCKET_ACCESS_CONTROL_PORT:
        {
          GSocketAddress *addr;
          guint16 port;

          addr = g_socket_get_local_address (self->priv->client_socket, &error);
          if (addr == NULL)
            {
              DEBUG ("Failed to get local address of client socket: %s",
                  error->message);

              operation_failed (self, error);
              g_error_free (error);
              return;
            }

          port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr));
          self->priv->access_control_param = tp_g_value_slice_new_uint (port);

          g_object_unref (addr);
        }
        break;

      case TP_SOCKET_ACCESS_CONTROL_CREDENTIALS:
        self->priv->access_control_param = tp_g_value_slice_new_byte (
            g_random_int_range (0, G_MAXUINT8));
        break;

      default:
        g_assert_not_reached ();
    }

  /* Call Accept */
  tp_cli_channel_type_stream_tube_call_accept (TP_CHANNEL (self), -1,
      self->priv->socket_type, self->priv->access_control,
      self->priv->access_control_param, _channel_accepted,
      NULL, NULL, G_OBJECT (self));
}