Index: configure.in
===================================================================
--- configure.in	(révision 434)
+++ configure.in	(copie de travail)
@@ -31,12 +31,13 @@
 LIBGNOME_REQUIRED=2.0.0
 LIBGNOMEUI_REQUIRED=2.0.0
 LIBESD_REQUIRED=0.2.36
+LIBEMPATHY_REQUIRED=0.14
 
 dnl *****************************************
 dnl libgnome, libgnomeui needed for all utils
 dnl *****************************************
 
-PKG_CHECK_MODULES(GTET, gtk+-2.0 >= $LIBGTK_REQUIRED libgnome-2.0 >= $LIBGNOME_REQUIRED libgnomeui-2.0 >= $LIBGNOMEUI_REQUIRED)
+PKG_CHECK_MODULES(GTET, gtk+-2.0 >= $LIBGTK_REQUIRED libgnome-2.0 >= $LIBGNOME_REQUIRED libgnomeui-2.0 >= $LIBGNOMEUI_REQUIRED libempathy >= $LIBEMPATHY_REQUIRED libempathy-gtk >= $LIBEMPATHY_REQUIRED)
 AC_SUBST(GTET_CFLAGS)
 AC_SUBST(GTET_LIBS)
 
Index: src/commands.c
===================================================================
--- src/commands.c	(révision 434)
+++ src/commands.c	(copie de travail)
@@ -43,6 +43,7 @@
 
 GnomeUIInfo gamemenu[] = {
     GNOMEUIINFO_ITEM(N_("_Connect to server..."), NULL, connect_command, NULL),
+    GNOMEUIINFO_ITEM(N_("_Play with a contact..."), NULL, contact_command, NULL),
     GNOMEUIINFO_ITEM(N_("_Disconnect from server"), NULL, disconnect_command, NULL),
     GNOMEUIINFO_SEPARATOR,
     GNOMEUIINFO_ITEM(N_("Change _team..."), NULL, team_command, NULL),
@@ -80,6 +81,7 @@
 
 GnomeUIInfo toolbar[] = {
     GNOMEUIINFO_ITEM_DATA(N_("Connect"), N_("Connect to a server"), connect_command, NULL, connect_xpm),
+    GNOMEUIINFO_ITEM_DATA(N_("Play"), N_("Play with a contact"), contact_command, NULL, connect_xpm),
     GNOMEUIINFO_ITEM_DATA(N_("Disconnect"), N_("Disconnect from the current server"), disconnect_command, NULL, disconnect_xpm),
     GNOMEUIINFO_SEPARATOR,
     GNOMEUIINFO_ITEM_DATA(N_("Start game"), N_("Start a new game"), start_command, NULL, play_xpm),
@@ -113,8 +115,8 @@
   gtk_menu_item_set_accel_path (GTK_MENU_ITEM (gamemenu[7].widget), "<GTetrinet-Main>/Game/Stop");
 
   gnome_app_create_toolbar (app, toolbar);
-  gtk_widget_hide (toolbar[4].widget);
-  gtk_widget_hide (toolbar[1].widget);
+  gtk_widget_hide (toolbar[5].widget);
+  gtk_widget_hide (toolbar[2].widget);
 }
 
 /* callbacks */
@@ -124,6 +126,11 @@
     connectdialog_new ();
 }
 
+void contact_command (void)
+{
+  contactdialog_new ();
+}
+
 void disconnect_command (void)
 {
     client_disconnect ();
@@ -151,26 +158,26 @@
 
 void show_connect_button (void)
 {
-  gtk_widget_hide (toolbar[1].widget);
+  gtk_widget_hide (toolbar[2].widget);
   gtk_widget_show (toolbar[0].widget);
 }
 
 void show_disconnect_button (void)
 {
   gtk_widget_hide (toolbar[0].widget);
-  gtk_widget_show (toolbar[1].widget);
+  gtk_widget_show (toolbar[2].widget);
 }
 
 void show_stop_button (void)
 {
-  gtk_widget_hide (toolbar[3].widget);
-  gtk_widget_show (toolbar[4].widget);
+  gtk_widget_hide (toolbar[4].widget);
+  gtk_widget_show (toolbar[5].widget);
 }
 
 void show_start_button (void)
 {
-  gtk_widget_hide (toolbar[4].widget);
-  gtk_widget_show (toolbar[3].widget);
+  gtk_widget_hide (toolbar[5].widget);
+  gtk_widget_show (toolbar[4].widget);
 }
 
 void end_command (void)
@@ -201,36 +208,36 @@
 {
     if (connected) {
         gtk_widget_set_sensitive (gamemenu[0].widget, FALSE);
-        gtk_widget_set_sensitive (gamemenu[1].widget, TRUE);
+        gtk_widget_set_sensitive (gamemenu[2].widget, TRUE);
 
         gtk_widget_set_sensitive (toolbar[0].widget, FALSE);
-        gtk_widget_set_sensitive (toolbar[1].widget, TRUE);
+        gtk_widget_set_sensitive (toolbar[2].widget, TRUE);
     }
     else {
         gtk_widget_set_sensitive (gamemenu[0].widget, TRUE);
-        gtk_widget_set_sensitive (gamemenu[1].widget, FALSE);
+        gtk_widget_set_sensitive (gamemenu[2].widget, FALSE);
 
         gtk_widget_set_sensitive (toolbar[0].widget, TRUE);
-        gtk_widget_set_sensitive (toolbar[1].widget, FALSE);
+        gtk_widget_set_sensitive (toolbar[2].widget, FALSE);
     }
     if (moderator) {
         if (ingame) {
-            gtk_widget_set_sensitive (gamemenu[5].widget, FALSE);
-            gtk_widget_set_sensitive (gamemenu[6].widget, TRUE);
+            gtk_widget_set_sensitive (gamemenu[6].widget, FALSE);
             gtk_widget_set_sensitive (gamemenu[7].widget, TRUE);
+            gtk_widget_set_sensitive (gamemenu[8].widget, TRUE);
 
-            gtk_widget_set_sensitive (toolbar[3].widget, FALSE);
-            gtk_widget_set_sensitive (toolbar[4].widget, TRUE);
+            gtk_widget_set_sensitive (toolbar[4].widget, FALSE);
             gtk_widget_set_sensitive (toolbar[5].widget, TRUE);
+            gtk_widget_set_sensitive (toolbar[6].widget, TRUE);
         }
         else {
             gtk_widget_set_sensitive (gamemenu[5].widget, TRUE);
             gtk_widget_set_sensitive (gamemenu[6].widget, FALSE);
             gtk_widget_set_sensitive (gamemenu[7].widget, FALSE);
 
-            gtk_widget_set_sensitive (toolbar[3].widget, TRUE);
-            gtk_widget_set_sensitive (toolbar[4].widget, FALSE);
+            gtk_widget_set_sensitive (toolbar[4].widget, TRUE);
             gtk_widget_set_sensitive (toolbar[5].widget, FALSE);
+            gtk_widget_set_sensitive (toolbar[6].widget, FALSE);
         }
     }
     else {
@@ -238,19 +245,19 @@
         gtk_widget_set_sensitive (gamemenu[6].widget, FALSE);
         gtk_widget_set_sensitive (gamemenu[7].widget, FALSE);
 
-        gtk_widget_set_sensitive (toolbar[3].widget, FALSE);
         gtk_widget_set_sensitive (toolbar[4].widget, FALSE);
         gtk_widget_set_sensitive (toolbar[5].widget, FALSE);
+        gtk_widget_set_sensitive (toolbar[6].widget, FALSE);
     }
     if (ingame || spectating) {
         gtk_widget_set_sensitive (gamemenu[3].widget, FALSE);
 
-        gtk_widget_set_sensitive (toolbar[7].widget, FALSE);
+        gtk_widget_set_sensitive (toolbar[8].widget, FALSE);
     }
     else {
         gtk_widget_set_sensitive (gamemenu[3].widget, TRUE);
 
-        gtk_widget_set_sensitive (toolbar[7].widget, TRUE);
+        gtk_widget_set_sensitive (toolbar[8].widget, TRUE);
     }
 
     partyline_connectstatus (connected);
Index: src/gtetrinet.c
===================================================================
--- src/gtetrinet.c	(révision 434)
+++ src/gtetrinet.c	(copie de travail)
@@ -63,7 +63,7 @@
 GtkWidget *app;
 
 char *option_connect = 0, *option_nick = 0, *option_team = 0, *option_pass = 0;
-int option_spec = 0;
+int option_spec = 0, option_port = 0;
 
 int gamemode = ORIGINAL;
 
@@ -75,6 +75,7 @@
 
 static const struct poptOption options[] = {
     {"connect", 'c', POPT_ARG_STRING, &option_connect, 0, N_("Connect to server"), N_("SERVER")},
+    {"port", 'P', POPT_ARG_INT, &option_port, 0, N_("Port to use for connection"), N_("PORT")},
     {"nickname", 'n', POPT_ARG_STRING, &option_nick, 0, N_("Set nickname to use"), N_("NICKNAME")},
     {"team", 't', POPT_ARG_STRING, &option_team, 0, N_("Set team name"), N_("TEAM")},
     {"spectate", 's', POPT_ARG_NONE, &option_spec, 0, N_("Connect as a spectator"), NULL},
@@ -317,15 +318,16 @@
             "option_team: %s\n"
             "option_pass: %s\n"
             "option_spec: %i\n",
+            "option_port: %d\n",
             option_connect, option_nick, option_team,
-            option_pass, option_spec);
+            option_pass, option_spec, option_port);
 #endif
     if (option_nick) GTET_O_STRCPY(nick, option_nick);
     if (option_team) GTET_O_STRCPY(team, option_team);
     if (option_pass) GTET_O_STRCPY(specpassword, option_pass);
     if (option_spec) spectating = TRUE;
     if (option_connect) {
-        client_init (option_connect, nick);
+        client_init (option_connect, option_port, nick);
     }
 
     /* Don't schedule if data is ready, glib should do this itself,
Index: src/commands.h
===================================================================
--- src/commands.h	(révision 434)
+++ src/commands.h	(copie de travail)
@@ -4,6 +4,7 @@
 void make_menus (GnomeApp *app);
 
 void connect_command (void);
+void contact_command (void);
 void disconnect_command (void);
 void team_command (void);
 #ifdef ENABLE_DETACH
Index: src/client.c
===================================================================
--- src/client.c	(révision 434)
+++ src/client.c	(copie de travail)
@@ -47,6 +47,7 @@
 
 int connected;
 char server[128];
+int port;
 
 static int sock;
 static GIOChannel *io_channel;
@@ -159,11 +160,15 @@
 enum inmsg_type inmsg_translate (char *str);
 char *outmsg_translate (enum outmsg_type);
 
-void client_init (const char *s, const char *n)
+void client_init (const char *s, int p, const char *n)
 {
     int i;
     GTET_O_STRCPY(server, s);
     GTET_O_STRCPY(nick, n);
+    if (p != 0)
+      port = p;
+    else
+      port = PORT;
 
     connectingdialog_new ();
 
@@ -304,7 +309,7 @@
     /* set up the connection */
 
 #ifdef USE_IPV6
-    snprintf(service, 9, "%d", spectating?SPECPORT:PORT);
+    snprintf(service, 9, "%d", spectating?SPECPORT:port);
     memset(&hints, 0, sizeof(hints));
     hints.ai_family = AF_UNSPEC;
     hints.ai_socktype = SOCK_STREAM;
@@ -351,7 +356,7 @@
     memset (&sa, 0, sizeof (sa));
     memcpy (&sa.sin_addr, h->h_addr, h->h_length);
     sa.sin_family = h->h_addrtype;
-    sa.sin_port = htons (spectating?SPECPORT:PORT);
+    sa.sin_port = htons (spectating?SPECPORT:port);
 
     sock = socket (sa.sin_family, SOCK_STREAM, 0);
     if (sock < 0)
Index: src/dialogs.c
===================================================================
--- src/dialogs.c	(révision 434)
+++ src/dialogs.c	(copie de travail)
@@ -26,6 +26,16 @@
 #include <sys/types.h>
 #include <dirent.h>
 
+#include <libempathy/empathy-contact-manager.h>
+#include <libempathy/empathy-contact.h>
+#include <libempathy/empathy-utils.h>
+#include <libempathy-gtk/empathy-contact-list-view.h>
+#include <libmissioncontrol/mc-account.h>
+#include <libmissioncontrol/mission-control.h>
+#include <libtelepathy/tp-chan-type-tubes-gen.h>
+#include <libtelepathy/tp-helpers.h>
+#include <libtelepathy/tp-chan.h>
+
 #include "gtetrinet.h"
 #include "config.h"
 #include "client.h"
@@ -37,13 +47,17 @@
 #include "string.h"
 #include "partyline.h"
 
+#define SOCKET_ADDRESS_IPV4_TYPE \
+    dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_UINT, \
+        G_TYPE_INVALID)
+
 extern GConfClient *gconf_client;
 extern GtkWidget *app;
 
 /*****************************************************/
 /* connecting dialog - a dialog with a cancel button */
 /*****************************************************/
-static GtkWidget *connectingdialog = 0, *connectdialog;
+static GtkWidget *connectingdialog = 0, *connectdialog, *contactdialog;
 static GtkWidget *progressbar;
 static gint timeouttag = 0;
 
@@ -236,7 +250,7 @@
         g_strstrip (nick); /* we remove leading and trailing whitespaces */
         if (g_utf8_strlen (nick, -1) > 0)
         {
-          client_init (server1, nick);
+          client_init (server1, 0, nick);
         }
         else
         {
@@ -1081,3 +1095,157 @@
                       GTK_SIGNAL_FUNC(prefdialog_response), NULL);
     gtk_widget_show_all (prefdialog);
 }
+
+/**************************/
+/* the contact dialog */
+/**************************/
+static EmpathyContactManager *contact_manager = NULL;
+static EmpathyContactListView *contact_list_view = NULL;
+static EmpathyContactListStore *contact_list_store = NULL;
+
+void contactdialog_button (GtkDialog *dialog, gint result)
+{
+    if (result == GTK_RESPONSE_OK)
+      {
+        MissionControl *mc = empathy_mission_control_new ();
+        DBusGConnection *bus = tp_get_bus ();
+        EmpathyContact *selected_contact;
+        gchar *nick;
+        const gchar *server1;
+        guint contact_handle = 0;
+        McAccount *mc_account = NULL;
+        GError *err = NULL;
+        gchar *argv[] = { "/usr/games/tetrinet-server", NULL };
+        TpConn *conn;
+        TpChan *tubes_chan;
+        GHashTable *parameters;
+        GValue address = {0,}, unused = {0,};
+        guint tube_id;
+        DBusGProxy *tube_iface;
+
+        selected_contact = empathy_contact_list_view_get_selected (
+            contact_list_view);
+        contact_handle = empathy_contact_get_handle (selected_contact);
+
+        mc_account = empathy_contact_get_account (selected_contact);
+
+        /* FIXME check if the server is running before trying to launch it */
+        /* Launch the tetrinet server */
+        if (!g_spawn_async (NULL, argv, NULL, 0, NULL, NULL, NULL, &err))
+          {
+            GtkWidget *dialog_error;
+
+            dialog_error = gtk_message_dialog_new (GTK_WINDOW (dialog),
+                GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+                "Launch of tetrinet-server failed: %s", err->message);
+            gtk_dialog_run (GTK_DIALOG (dialog_error));
+
+            g_error_free (err);
+            g_object_unref (mc);
+            return;
+          }
+
+        conn = mission_control_get_connection (mc, mc_account, NULL);
+        g_assert (conn != NULL);
+
+        tubes_chan = tp_conn_new_channel (bus, conn,
+            dbus_g_proxy_get_bus_name (DBUS_G_PROXY (conn)),
+            TP_IFACE_CHANNEL_TYPE_TUBES, TP_HANDLE_TYPE_CONTACT,
+            contact_handle, FALSE);
+        g_assert (tubes_chan != NULL);
+
+        parameters = g_hash_table_new (g_str_hash, g_str_equal);
+
+        g_value_init (&address, SOCKET_ADDRESS_IPV4_TYPE);
+        g_value_take_boxed (&address, dbus_g_type_specialized_construct (
+             SOCKET_ADDRESS_IPV4_TYPE));
+        dbus_g_type_struct_set (&address,
+            0, "127.0.0.1",
+            1, 31457,
+            G_MAXUINT);
+
+        /* dbus-glib is not happy if we don't initialize this */
+        g_value_init (&unused, G_TYPE_STRING);
+
+        tube_iface = tp_chan_get_interface (tubes_chan,
+            TELEPATHY_CHAN_IFACE_TUBES_QUARK);
+
+        if (!tp_chan_type_tubes_offer_stream_tube (tube_iface,
+            "x-tetrinet", parameters, TP_SOCKET_ADDRESS_TYPE_IPV4, &address,
+            TP_SOCKET_ACCESS_CONTROL_LOCALHOST, &unused, &tube_id, &err))
+          {
+            GtkWidget *dialog_error;
+
+            dialog_error = gtk_message_dialog_new (GTK_WINDOW (dialog),
+                GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+                "Tubes offering failed: %s", err->message);
+            gtk_dialog_run (GTK_DIALOG (dialog_error));
+
+            g_error_free (err);
+            g_object_unref (mc);
+            return;
+          }
+        g_print ("tube id: %d\n", tube_id);
+
+        g_hash_table_destroy (parameters);
+
+        /* connect to our server */
+        spectating = FALSE;
+
+        nick = gconf_client_get_string (gconf_client,
+            "/apps/gtetrinet/player/nickname", NULL);
+        client_init ("127.0.0.1", 0, nick);
+      }
+
+    gtk_widget_destroy (contactdialog);
+}
+
+void contactdialog_destroy (void)
+{
+    connecting = FALSE;
+}
+
+void contactdialog_new (void)
+{
+    GtkWidget *widget, *table1, *table2, *frame;
+    /* check if dialog is already displayed */
+    if (connecting) 
+    {
+      gtk_window_present (GTK_WINDOW (contactdialog));
+      return;
+    }
+    connecting = TRUE;
+
+   contact_manager = empathy_contact_manager_new ();
+   contact_list_store = empathy_contact_list_store_new (EMPATHY_CONTACT_LIST (
+         contact_manager));
+   g_object_set (contact_list_store,
+       "is-compact", TRUE,
+       "show-avatars", FALSE,
+       "show-offline", FALSE,
+       "sort-criterium", EMPATHY_CONTACT_LIST_STORE_SORT_NAME,
+        NULL);
+   contact_list_view = empathy_contact_list_view_new (contact_list_store, EMPATHY_CONTACT_LIST_FEATURE_ALL);
+
+    /* make dialog that asks for address/nickname */
+    contactdialog = gtk_dialog_new_with_buttons (_("Play with a contact"),
+                                                 GTK_WINDOW (app),
+                                                 GTK_DIALOG_NO_SEPARATOR,
+                                                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                                 GTK_STOCK_OK, GTK_RESPONSE_OK,
+                                                 NULL);
+    gtk_dialog_set_default_response (GTK_DIALOG (contactdialog), GTK_RESPONSE_OK);
+    gtk_window_set_resizable (GTK_WINDOW (contactdialog), TRUE);
+    g_signal_connect (G_OBJECT (contactdialog), "response",
+                      GTK_SIGNAL_FUNC (contactdialog_button), NULL);
+    g_signal_connect (G_OBJECT (contactdialog), "destroy",
+                      GTK_SIGNAL_FUNC (contactdialog_destroy), NULL);
+
+   gtk_widget_show (GTK_WIDGET (contact_list_view));
+   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (contactdialog)->vbox),
+       GTK_WIDGET (contact_list_view));
+
+   gtk_widget_show (contactdialog);
+   g_object_unref (contact_manager);
+   g_object_unref (contact_list_store);
+}
Index: src/client.h
===================================================================
--- src/client.h	(révision 434)
+++ src/client.h	(copie de travail)
@@ -31,7 +31,7 @@
 };
 
 /* functions for connecting and disconnecting */
-extern void client_init (const char *server, const char *nick);
+extern void client_init (const char *server, int port, const char *nick);
 extern void client_disconnect (void);
 
 /* for sending stuff back and forth */
Index: src/dialogs.h
===================================================================
--- src/dialogs.h	(révision 434)
+++ src/dialogs.h	(copie de travail)
@@ -4,3 +4,4 @@
 extern void connectingdialog_new (void);
 extern void connectdialog_connected (void);
 extern void prefdialog_new (void);
+extern void contactdialog_new (void);
