]> git.0d.be Git - empathy.git/blobdiff - libempathy-gtk/empathy-new-call-dialog.c
factor out start_gnome_contacts()
[empathy.git] / libempathy-gtk / empathy-new-call-dialog.c
index 2d35fadecfc486bcb74814c565d154c9815c5575..0fecedde5c45682c15d20016e40b3a40aa5c3619 100644 (file)
 
 #include <telepathy-glib/interfaces.h>
 
+#include <telepathy-yell/telepathy-yell.h>
+
 #include <libempathy/empathy-tp-contact-factory.h>
-#include <libempathy/empathy-contact-manager.h>
+#include <libempathy/empathy-camera-monitor.h>
 #include <libempathy/empathy-utils.h>
+#include <libempathy/empathy-request-util.h>
 
 #define DEBUG_FLAG EMPATHY_DEBUG_CONTACT
 #include <libempathy/empathy-debug.h>
 
+#include <libempathy-gtk/empathy-contact-chooser.h>
 #include <libempathy-gtk/empathy-ui-utils.h>
 #include <libempathy-gtk/empathy-images.h>
 
 #include "empathy-new-call-dialog.h"
 #include "empathy-account-chooser.h"
+#include "empathy-call-utils.h"
 
 static EmpathyNewCallDialog *dialog_singleton = NULL;
 
 G_DEFINE_TYPE(EmpathyNewCallDialog, empathy_new_call_dialog,
-               EMPATHY_TYPE_CONTACT_SELECTOR_DIALOG)
-
-typedef struct _EmpathyNewCallDialogPriv EmpathyNewCallDialogPriv;
-
-typedef struct {
-  EmpathyAccountChooserFilterResultCallback callback;
-  gpointer                                  user_data;
-} FilterCallbackData;
+               GTK_TYPE_DIALOG)
 
 struct _EmpathyNewCallDialogPriv {
-  GtkWidget *check_video;
-};
+  GtkWidget *chooser;
+  GtkWidget *button_audio;
+  GtkWidget *button_video;
 
-#define GET_PRIV(o) \
-  (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_NEW_CALL_DIALOG, \
-    EmpathyNewCallDialogPriv))
+  EmpathyCameraMonitor *monitor;
+};
 
-static void
-create_media_channel_cb (GObject *source,
-    GAsyncResult *result,
-    gpointer user_data)
+/* Re-use the accept and ok Gtk response so we are sure they won't be used
+ * when the dialog window is closed for example */
+enum
 {
-  GError *error = NULL;
-
-  if (!tp_account_channel_request_create_channel_finish (
-        TP_ACCOUNT_CHANNEL_REQUEST (source), result, &error))
-    {
-      DEBUG ("Failed to create media channel: %s", error->message);
-      g_error_free (error);
-    }
-}
+  RESPONSE_AUDIO = GTK_RESPONSE_ACCEPT,
+  RESPONSE_VIDEO = GTK_RESPONSE_OK,
+};
 
 /**
  * SECTION:empathy-new-call-dialog
@@ -87,132 +78,43 @@ create_media_channel_cb (GObject *source,
  */
 
 static void
-call_contact (TpAccount *account,
-    const gchar *contact_id,
-    gboolean video,
-    gint64 timestamp)
+empathy_new_call_dialog_response (GtkDialog *dialog,
+    int response_id)
 {
-  GHashTable *request;
-  TpAccountChannelRequest *req;
-
-  request = tp_asv_new (
-      TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
-        TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
-      TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
-      TP_PROP_CHANNEL_TARGET_ID, G_TYPE_STRING, contact_id,
-      TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_AUDIO, G_TYPE_BOOLEAN,
-        TRUE,
-      TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_VIDEO, G_TYPE_BOOLEAN,
-        video,
-      NULL);
-
-  req = tp_account_channel_request_new (account, request, timestamp);
-
-  tp_account_channel_request_create_channel_async (req, NULL, NULL,
-      create_media_channel_cb, NULL);
-
-  g_object_unref (req);
-}
+  EmpathyNewCallDialog *self = (EmpathyNewCallDialog *) dialog;
+  FolksIndividual *individual;
+  EmpathyContact *contact;
 
-static void
-empathy_new_call_dialog_response (GtkDialog *dialog, int response_id)
-{
-  EmpathyNewCallDialogPriv *priv = GET_PRIV (dialog);
-  gboolean video;
-  TpAccount *account;
-  const gchar *contact_id;
-
-  if (response_id != GTK_RESPONSE_ACCEPT) goto out;
+  if (response_id != RESPONSE_AUDIO &&
+      response_id != RESPONSE_VIDEO)
+    goto out;
 
-  contact_id = empathy_contact_selector_dialog_get_selected (
-      EMPATHY_CONTACT_SELECTOR_DIALOG (dialog), NULL, &account);
+  individual = empathy_contact_chooser_dup_selected (
+      EMPATHY_CONTACT_CHOOSER (self->priv->chooser));
+  if (individual == NULL) goto out;
 
-  if (EMP_STR_EMPTY (contact_id) || account == NULL) goto out;
+  empathy_individual_can_audio_video_call (individual, NULL, NULL, &contact);
+  g_assert (contact != NULL);
 
-  /* check if video is enabled now because the dialog will be destroyed once
-   * we return from this function. */
-  video = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->check_video));
+  empathy_call_new_with_streams (empathy_contact_get_id (contact),
+      empathy_contact_get_account (contact), TRUE,
+      response_id == RESPONSE_VIDEO, empathy_get_current_action_time ());
 
-  call_contact (account, contact_id, video, gtk_get_current_event_time ());
+  g_object_unref (individual);
+  g_object_unref (contact);
 
 out:
   gtk_widget_destroy (GTK_WIDGET (dialog));
 }
 
 static void
-conn_prepared_cb (GObject *conn,
-    GAsyncResult *result,
-    gpointer user_data)
+empathy_new_call_dialog_dispose (GObject *object)
 {
-  FilterCallbackData *data = user_data;
-  GError *myerr = NULL;
-  TpCapabilities *caps;
-  GPtrArray *classes;
-  guint i;
-
-  if (!tp_proxy_prepare_finish (conn, result, &myerr))
-      goto out;
-
-  caps = tp_connection_get_capabilities (TP_CONNECTION (conn));
-  classes = tp_capabilities_get_channel_classes (caps);
-
-  for (i = 0; i < classes->len; i++)
-    {
-      GHashTable *fixed;
-      GStrv allowed;
-      const gchar *chan_type;
-
-      tp_value_array_unpack (g_ptr_array_index (classes, i), 2,
-          &fixed, &allowed);
-
-      chan_type = tp_asv_get_string (fixed, TP_PROP_CHANNEL_CHANNEL_TYPE);
-
-      if (tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA))
-        continue;
-
-      if (tp_asv_get_uint32 (fixed, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL) !=
-          TP_HANDLE_TYPE_CONTACT)
-        continue;
-
-      data->callback (TRUE, data->user_data);
-      g_slice_free (FilterCallbackData, data);
-      return;
-    }
-
-out:
-  data->callback (FALSE, data->user_data);
-  g_slice_free (FilterCallbackData, data);
-}
-
-static void
-empathy_new_call_dialog_account_filter (EmpathyContactSelectorDialog *dialog,
-    EmpathyAccountChooserFilterResultCallback callback,
-    gpointer callback_data,
-    TpAccount *account)
-{
-  TpConnection *connection;
-  FilterCallbackData *cb_data;
-  GQuark features[] = { TP_CONNECTION_FEATURE_CAPABILITIES, 0 };
-
-  if (tp_account_get_connection_status (account, NULL) !=
-      TP_CONNECTION_STATUS_CONNECTED)
-    {
-      callback (FALSE, callback_data);
-      return;
-    }
+  EmpathyNewCallDialog *self = (EmpathyNewCallDialog *) object;
 
-  /* check if CM supports calls */
-  connection = tp_account_get_connection (account);
-  if (connection == NULL)
-    {
-      callback (FALSE, callback_data);
-      return;
-    }
+  tp_clear_object (&self->priv->monitor);
 
-  cb_data = g_slice_new0 (FilterCallbackData);
-  cb_data->callback = callback;
-  cb_data->user_data = callback_data;
-  tp_proxy_prepare_async (connection, features, conn_prepared_cb, cb_data);
+  G_OBJECT_CLASS (empathy_new_call_dialog_parent_class)->dispose (object);
 }
 
 static GObject *
@@ -240,37 +142,114 @@ empathy_new_call_dialog_constructor (GType type,
   return retval;
 }
 
+static gboolean
+filter_individual (EmpathyContactChooser *chooser,
+    FolksIndividual *individual,
+    gboolean is_online,
+    gboolean searching,
+    gpointer user_data)
+{
+  gboolean can_audio_call, can_video_call;
+
+  empathy_individual_can_audio_video_call (individual, &can_audio_call,
+      &can_video_call, NULL);
+
+  return can_audio_call || can_video_call;
+}
+
 static void
-empathy_new_call_dialog_init (EmpathyNewCallDialog *dialog)
+selection_changed_cb (GtkWidget *chooser,
+    FolksIndividual *selected,
+    EmpathyNewCallDialog *self)
 {
-  EmpathyContactSelectorDialog *parent = EMPATHY_CONTACT_SELECTOR_DIALOG (
-        dialog);
-  EmpathyNewCallDialogPriv *priv = GET_PRIV (dialog);
+  gboolean can_audio_call, can_video_call;
+
+  if (selected == NULL)
+    {
+      can_audio_call = can_video_call = FALSE;
+    }
+  else
+    {
+      empathy_individual_can_audio_video_call (selected, &can_audio_call,
+          &can_video_call, NULL);
+    }
+
+  gtk_widget_set_sensitive (self->priv->button_audio, can_audio_call);
+  gtk_widget_set_sensitive (self->priv->button_video, can_video_call);
+}
+
+static void
+selection_activate_cb (GtkWidget *chooser,
+    EmpathyNewCallDialog *self)
+{
+  gtk_dialog_response (GTK_DIALOG (self), RESPONSE_AUDIO);
+}
+
+static void
+empathy_new_call_dialog_init (EmpathyNewCallDialog *self)
+{
+  GtkWidget *label;
   GtkWidget *image;
+  GtkWidget *content;
+
+  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+      EMPATHY_TYPE_NEW_CALL_DIALOG, EmpathyNewCallDialogPriv);
+
+  self->priv->monitor = empathy_camera_monitor_dup_singleton ();
+
+  content = gtk_dialog_get_content_area (GTK_DIALOG (self));
 
-  /* add video toggle */
-  priv->check_video = gtk_check_button_new_with_mnemonic (_("Send _Video"));
+  label = gtk_label_new (_("Enter a contact identifier or phone number:"));
+  gtk_box_pack_start (GTK_BOX (content), label, FALSE, FALSE, 0);
+  gtk_widget_show (label);
 
-  gtk_box_pack_end (GTK_BOX (parent->vbox), priv->check_video,
-      FALSE, TRUE, 0);
+  /* contact chooser */
+  self->priv->chooser = empathy_contact_chooser_new ();
 
-  gtk_widget_show (priv->check_video);
+  empathy_contact_chooser_set_filter_func (
+      EMPATHY_CONTACT_CHOOSER (self->priv->chooser), filter_individual, self);
 
-  /* add chat button */
-  parent->button_action = gtk_button_new_with_mnemonic (_("C_all"));
+  gtk_box_pack_start (GTK_BOX (content), self->priv->chooser, TRUE, TRUE, 6);
+  gtk_widget_show (self->priv->chooser);
+
+  g_signal_connect (self->priv->chooser, "selection-changed",
+      G_CALLBACK (selection_changed_cb), self);
+  g_signal_connect (self->priv->chooser, "activate",
+      G_CALLBACK (selection_activate_cb), self);
+
+  /* close button */
+  gtk_dialog_add_button (GTK_DIALOG (self),
+      GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
+
+  /* add video button */
+  self->priv->button_video = gtk_button_new_with_mnemonic (_("_Video Call"));
+  image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_VIDEO_CALL,
+      GTK_ICON_SIZE_BUTTON);
+  gtk_button_set_image (GTK_BUTTON (self->priv->button_video), image);
+
+  gtk_dialog_add_action_widget (GTK_DIALOG (self), self->priv->button_video,
+      RESPONSE_VIDEO);
+  gtk_widget_show (self->priv->button_video);
+
+  /* add audio button */
+  self->priv->button_audio = gtk_button_new_with_mnemonic (_("_Audio Call"));
   image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_VOIP,
       GTK_ICON_SIZE_BUTTON);
-  gtk_button_set_image (GTK_BUTTON (parent->button_action), image);
+  gtk_button_set_image (GTK_BUTTON (self->priv->button_audio), image);
 
-  gtk_dialog_add_action_widget (GTK_DIALOG (dialog), parent->button_action,
-      GTK_RESPONSE_ACCEPT);
-  gtk_widget_show (parent->button_action);
+  gtk_dialog_add_action_widget (GTK_DIALOG (self), self->priv->button_audio,
+      RESPONSE_AUDIO);
+  gtk_widget_show (self->priv->button_audio);
 
   /* Tweak the dialog */
-  gtk_window_set_title (GTK_WINDOW (dialog), _("New Call"));
-  gtk_window_set_role (GTK_WINDOW (dialog), "new_call");
+  gtk_window_set_title (GTK_WINDOW (self), _("New Call"));
+  gtk_window_set_role (GTK_WINDOW (self), "new_call");
 
-  gtk_widget_set_sensitive (parent->button_action, FALSE);
+  /* Set a default height so a few contacts are displayed */
+  gtk_window_set_default_size (GTK_WINDOW (self), -1, 400);
+
+  gtk_widget_set_sensitive (self->priv->button_audio, FALSE);
+  gtk_widget_set_sensitive (self->priv->button_video, FALSE);
 }
 
 static void
@@ -279,16 +258,13 @@ empathy_new_call_dialog_class_init (
 {
   GObjectClass *object_class = G_OBJECT_CLASS (class);
   GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (class);
-  EmpathyContactSelectorDialogClass *selector_dialog_class = \
-    EMPATHY_CONTACT_SELECTOR_DIALOG_CLASS (class);
 
   g_type_class_add_private (class, sizeof (EmpathyNewCallDialogPriv));
 
   object_class->constructor = empathy_new_call_dialog_constructor;
+  object_class->dispose = empathy_new_call_dialog_dispose;
 
   dialog_class->response = empathy_new_call_dialog_response;
-
-  selector_dialog_class->account_filter = empathy_new_call_dialog_account_filter;
 }
 
 /**