[farsight2/master] Move examples to examples dir

Olivier Crête olivier.crete at collabora.co.uk
Mon Feb 23 13:47:42 PST 2009


---
 .gitignore                         |    6 +-
 Makefile.am                        |    6 +-
 configure.ac                       |    5 +-
 examples/Makefile.am               |    2 +
 examples/commandline/Makefile.am   |   14 +
 examples/commandline/simple-call.c |  339 +++++++++++++
 examples/gui/Makefile.am           |    1 +
 examples/gui/fs2-gui.glade         |  705 +++++++++++++++++++++++++++
 examples/gui/fs2-gui.py            |  929 ++++++++++++++++++++++++++++++++++++
 examples/gui/fs2_gui_net.py        |  456 ++++++++++++++++++
 tests/Makefile.am                  |    4 +-
 tests/commandline/Makefile.am      |   14 -
 tests/commandline/simple-call.c    |  339 -------------
 tests/gui/Makefile.am              |    1 -
 tests/gui/fs2-gui.glade            |  705 ---------------------------
 tests/gui/fs2-gui.py               |  929 ------------------------------------
 tests/gui/fs2_gui_net.py           |  456 ------------------
 17 files changed, 2458 insertions(+), 2453 deletions(-)
 create mode 100644 examples/Makefile.am
 create mode 100644 examples/commandline/Makefile.am
 create mode 100644 examples/commandline/simple-call.c
 create mode 100644 examples/gui/Makefile.am
 create mode 100644 examples/gui/fs2-gui.glade
 create mode 100755 examples/gui/fs2-gui.py
 create mode 100644 examples/gui/fs2_gui_net.py
 delete mode 100644 tests/commandline/Makefile.am
 delete mode 100644 tests/commandline/simple-call.c
 delete mode 100644 tests/gui/Makefile.am
 delete mode 100644 tests/gui/fs2-gui.glade
 delete mode 100755 tests/gui/fs2-gui.py
 delete mode 100644 tests/gui/fs2_gui_net.py

diff --git a/.gitignore b/.gitignore
index 41cb899..8a1744f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -80,9 +80,9 @@ tests/check/rtp/sendcodecs
 tests/check/utils/binadded
 tests/check/elements/rtcpfilter
 tests/rtp/codec-discovery
-tests/commandline/simple-call
-tests/gui/*.pyo
-tests/gui/*.pyc
+examples/commandline/simple-call
+examples/gui/*.pyo
+examples/gui/*.pyc
 
 aclocal.m4
 autom4te.cache
diff --git a/Makefile.am b/Makefile.am
index 13a165a..4fea98b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,7 +15,8 @@ SUBDIRS = 			\
 	docs			\
 	common			\
 	common-modified		\
-	m4
+	m4			\
+	examples
 #	pkgconfig
 
 DIST_SUBDIRS = 			\
@@ -27,7 +28,8 @@ DIST_SUBDIRS = 			\
 	docs			\
 	common			\
 	common-modified		\
-	m4
+	m4			\
+	examples
 #	pkgconfig
 
 EXTRA_DIST = \
diff --git a/configure.ac b/configure.ac
index b0715e0..e75269e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -413,8 +413,9 @@ dnl pkgconfig/farsight2-uninstalled.pc
 tests/Makefile
 tests/check/Makefile
 tests/rtp/Makefile
-tests/gui/Makefile
-tests/commandline/Makefile
+examples/Makefile
+examples/gui/Makefile
+examples/commandline/Makefile
 docs/Makefile
 docs/libs/Makefile
 docs/plugins/Makefile
diff --git a/examples/Makefile.am b/examples/Makefile.am
new file mode 100644
index 0000000..3099ae2
--- /dev/null
+++ b/examples/Makefile.am
@@ -0,0 +1,2 @@
+
+SUBDIRS = gui commandline
diff --git a/examples/commandline/Makefile.am b/examples/commandline/Makefile.am
new file mode 100644
index 0000000..d374e67
--- /dev/null
+++ b/examples/commandline/Makefile.am
@@ -0,0 +1,14 @@
+
+noinst_PROGRAMS = simple-call
+
+
+AM_CFLAGS = \
+	-I$(top_srcdir)/gst/fsrtpconference/ \
+	$(FS2_INTERNAL_CFLAGS) \
+	$(FS2_CFLAGS) \
+	$(GST_CFLAGS) \
+	$(CFLAGS)
+
+LDADD = \
+	$(top_builddir)/gst-libs/gst/farsight/libgstfarsight-0.10.la \
+	$(GST_LIBS) 
diff --git a/examples/commandline/simple-call.c b/examples/commandline/simple-call.c
new file mode 100644
index 0000000..fbc56fb
--- /dev/null
+++ b/examples/commandline/simple-call.c
@@ -0,0 +1,339 @@
+/* Farsight 2 ad-hoc test for simple calls.
+ *
+ * Copyright (C) 2008 Collabora, Nokia
+ * @author: Olivier Crete <olivier.crete at collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+/*
+ * WARNING:
+ *
+ * Do not use this as an example of a proper use of farsight, it assumes that
+ * both ends have the EXACT same list of codec installed in the EXACT same order
+ */
+
+
+#include <stdlib.h>
+
+#include <glib.h>
+#include <gst/gst.h>
+#include <gst/farsight/fs-conference-iface.h>
+
+#define DEFAULT_AUDIOSRC       "alsasrc"
+#define DEFAULT_AUDIOSINK      "audioconvert ! audioresample ! audioconvert ! alsasink"
+
+typedef struct _TestSession
+{
+  FsSession *session;
+  FsStream *stream;
+} TestSession;
+
+
+static void
+print_error (GError *error)
+{
+  if (error)
+  {
+    g_error ("Error: %s:%d : %s", g_quark_to_string (error->domain),
+        error->code, error->message);
+  }
+}
+
+static void
+src_pad_added_cb (FsStream *stream, GstPad *pad, FsCodec *codec,
+    gpointer user_data)
+{
+  GstElement *pipeline = GST_ELEMENT_CAST (user_data);
+  GstElement *sink = NULL;
+  GError *error = NULL;
+  GstPad *pad2;
+
+  g_print ("Adding receive pipeline\n");
+
+  if (g_getenv ("AUDIOSINK"))
+    sink = gst_parse_bin_from_description (g_getenv ("AUDIOSINK"), TRUE,
+        &error);
+  else
+    sink = gst_parse_bin_from_description (DEFAULT_AUDIOSINK, TRUE,
+        &error);
+  print_error (error);
+  g_assert (sink);
+
+  g_assert (gst_bin_add (GST_BIN (pipeline), sink));
+
+
+  pad2 = gst_element_get_static_pad (sink, "sink");
+  g_assert (pad2);
+
+  g_assert (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (pad, pad2)));
+
+  g_assert (gst_element_set_state (sink, GST_STATE_PLAYING) !=
+      GST_STATE_CHANGE_FAILURE);
+
+  gst_object_unref (pad2);
+}
+
+static TestSession*
+add_audio_session (GstElement *pipeline, FsConference *conf, guint id,
+    FsParticipant *part, guint localport, const gchar *remoteip,
+    guint remoteport)
+{
+  TestSession *ses = g_slice_new0 (TestSession);
+  GError *error = NULL;
+  GstPad *pad = NULL, *pad2 = NULL;
+  GstElement *src = NULL;
+  GList *cands = NULL;
+  GList *codecs = NULL;
+  GParameter param = {0};
+  gboolean res;
+
+  ses->session = fs_conference_new_session (conf, FS_MEDIA_TYPE_AUDIO, &error);
+  print_error (error);
+  g_assert (ses->session);
+
+  g_object_get (ses->session, "sink-pad", &pad, NULL);
+
+  if (g_getenv ("AUDIOSRC"))
+    src = gst_parse_bin_from_description (g_getenv ("AUDIOSRC"), TRUE,
+        &error);
+  else
+    src = gst_parse_bin_from_description (DEFAULT_AUDIOSRC, TRUE,
+        &error);
+  print_error (error);
+  g_assert (src);
+
+  g_assert (gst_bin_add (GST_BIN (pipeline), src));
+
+  pad2 = gst_element_get_static_pad (src, "src");
+  g_assert (pad2);
+
+  g_assert (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (pad2, pad)));
+
+  gst_object_unref (pad2);
+  gst_object_unref (pad);
+
+
+  cands = g_list_prepend (NULL, fs_candidate_new ("", FS_COMPONENT_RTP,
+          FS_CANDIDATE_TYPE_HOST, FS_NETWORK_PROTOCOL_UDP, NULL, localport));
+
+  param.name = "preferred-local-candidates";
+  g_value_init (&param.value, FS_TYPE_CANDIDATE_LIST);
+  g_value_take_boxed (&param.value, cands);
+
+  ses->stream = fs_session_new_stream (ses->session, part, FS_DIRECTION_BOTH,
+      "rawudp", 1, &param, &error);
+  print_error (error);
+  g_assert (ses->stream);
+
+  g_value_unset (&param.value);
+
+  g_signal_connect (ses->stream, "src-pad-added",
+      G_CALLBACK (src_pad_added_cb), pipeline);
+
+  cands = g_list_prepend (NULL, fs_candidate_new ("", FS_COMPONENT_RTP,
+          FS_CANDIDATE_TYPE_HOST, FS_NETWORK_PROTOCOL_UDP, remoteip,
+          remoteport));
+
+  res = fs_stream_set_remote_candidates (ses->stream, cands, &error);
+  print_error (error);
+  g_assert (res);
+
+  fs_candidate_list_destroy (cands);
+
+  codecs = g_list_prepend (NULL,
+      fs_codec_new (FS_CODEC_ID_ANY, "PCMA", FS_MEDIA_TYPE_AUDIO, 0));
+  codecs = g_list_prepend (codecs,
+      fs_codec_new (FS_CODEC_ID_ANY, "PCMU", FS_MEDIA_TYPE_AUDIO, 0));
+
+  res = fs_session_set_codec_preferences (ses->session, codecs, &error);
+  print_error (error);
+  fs_codec_list_destroy (codecs);
+
+
+  g_object_get (ses->session, "codecs", &codecs, NULL);
+  res = fs_stream_set_remote_codecs (ses->stream, codecs, &error);
+  print_error (error);
+  g_assert (res);
+
+  return ses;
+}
+
+static gboolean
+async_bus_cb (GstBus *bus, GstMessage *message, gpointer user_data)
+{
+  switch (GST_MESSAGE_TYPE(message))
+  {
+    case GST_MESSAGE_ERROR:
+      {
+        GError *error = NULL;
+        gchar *debug_str = NULL;
+
+        gst_message_parse_error (message, &error, &debug_str);
+        g_error ("Got gst message: %s %s", error->message, debug_str);
+      }
+      break;
+    case GST_MESSAGE_WARNING:
+      {
+        GError *error = NULL;
+        gchar *debug_str = NULL;
+
+        gst_message_parse_warning (message, &error, &debug_str);
+        g_warning ("Got gst message: %s %s", error->message, debug_str);
+      }
+      break;
+    case GST_MESSAGE_ELEMENT:
+      {
+        const GstStructure *s = gst_message_get_structure (message);
+
+        if (gst_structure_has_name (s, "farsight-error"))
+        {
+          gint error;
+          const gchar *error_msg = gst_structure_get_string (s, "error-msg");
+          const gchar *debug_msg = gst_structure_get_string (s, "debug-msg");
+
+          g_assert (gst_structure_get_enum (s, "error-no", FS_TYPE_ERROR,
+                  &error));
+
+          if (FS_ERROR_IS_FATAL (error))
+            g_error ("Farsight fatal error: %d %s %s", error, error_msg,
+                debug_msg);
+          else
+            g_warning ("Farsight non-fatal error: %d %s %s", error, error_msg,
+                debug_msg);
+        }
+        else if (gst_structure_has_name (s, "farsight-new-local-candidate"))
+        {
+          const GValue *val = gst_structure_get_value (s, "candidate");
+          FsCandidate *cand = NULL;
+
+          g_assert (val);
+          cand = g_value_get_boxed (val);
+
+          g_print ("New candidate: %s %d\n", cand->ip, cand->port);
+        }
+        else if (gst_structure_has_name (s,
+                "farsight-local-candidates-prepared"))
+        {
+          g_print ("Local candidates prepared\n");
+        }
+        else if (gst_structure_has_name (s, "farsight-recv-codecs-changed"))
+        {
+          const GValue *val = gst_structure_get_value (s, "codecs");
+          GList *codecs = NULL;
+
+          g_assert (val);
+          codecs = g_value_get_boxed (val);
+
+          g_print ("Recv codecs changed:\n");
+          for (; codecs; codecs = g_list_next (codecs))
+          {
+            FsCodec *codec = codecs->data;
+            gchar *tmp = fs_codec_to_string (codec);
+            g_print ("%s\n", tmp);
+            g_free (tmp);
+          }
+        }
+        else if (gst_structure_has_name (s, "farsight-send-codec-changed"))
+        {
+          const GValue *val = gst_structure_get_value (s, "codec");
+          FsCodec *codec = NULL;
+          gchar *tmp;
+          g_assert (val);
+          codec = g_value_get_boxed (val);
+          tmp = fs_codec_to_string (codec);
+
+          g_print ("Send codec changed: %s\n", tmp);
+          g_free (tmp);
+        }
+      }
+      break;
+    default:
+      break;
+  }
+
+  return TRUE;
+}
+
+int main (int argc, char **argv)
+{
+  GMainLoop *loop = NULL;
+  GstElement *pipeline = NULL;
+  GstBus *bus = NULL;
+  const gchar *remoteip;
+  guint localport = 0;
+  guint remoteport = 0;
+  GstElement *conf = NULL;
+  FsParticipant *part = NULL;
+  GError *error = NULL;
+
+  gst_init (&argc, &argv);
+
+  if (argc != 4)
+  {
+    g_print ("Usage: %s <local port> <remoteip> <remoteport>\n",
+        argv[0]);
+    return 1;
+  }
+
+  localport = atoi (argv[1]);
+  remoteip = argv[2];
+  remoteport = atoi (argv[3]);
+
+  if (!localport || !remoteip || !remoteport)
+  {
+    g_print ("Usage: %s <local port> <remoteip> <remoteport>\n",
+        argv[0]);
+    return 2;
+  }
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  pipeline = gst_pipeline_new (NULL);
+
+  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+  gst_bus_add_watch (bus, async_bus_cb, pipeline);
+  gst_object_unref (bus);
+
+  conf = gst_element_factory_make ("fsrtpconference", NULL);
+  g_assert (conf);
+
+  part = fs_conference_new_participant (FS_CONFERENCE (conf), "test at ignore",
+      &error);
+  print_error (error);
+  g_assert (part);
+
+  g_assert (gst_bin_add (GST_BIN (pipeline), conf));
+
+
+  add_audio_session (pipeline, FS_CONFERENCE (conf), 1, part, localport,
+      remoteip, remoteport);
+
+
+  g_assert (gst_element_set_state (pipeline, GST_STATE_PLAYING) !=
+      GST_STATE_CHANGE_FAILURE);
+
+  g_main_loop_run (loop);
+
+  g_assert (gst_element_set_state (pipeline, GST_STATE_NULL) !=
+      GST_STATE_CHANGE_FAILURE);
+
+  g_object_unref (part);
+
+  gst_object_unref (pipeline);
+  g_main_loop_unref (loop);
+
+  return 0;
+}
diff --git a/examples/gui/Makefile.am b/examples/gui/Makefile.am
new file mode 100644
index 0000000..10a8a39
--- /dev/null
+++ b/examples/gui/Makefile.am
@@ -0,0 +1 @@
+EXTRA_DIST = fs2-gui.glade fs2_gui_net.py fs2-gui.py
diff --git a/examples/gui/fs2-gui.glade b/examples/gui/fs2-gui.glade
new file mode 100644
index 0000000..b1b4151
--- /dev/null
+++ b/examples/gui/fs2-gui.glade
@@ -0,0 +1,705 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--Generated with glade3 3.4.0 on Tue Jun 17 16:01:07 2008 -->
+<glade-interface>
+  <widget class="GtkWindow" id="main_window">
+    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+    <property name="border_width">6</property>
+    <property name="resizable">False</property>
+    <signal name="destroy" handler="shutdown"/>
+    <child>
+      <widget class="GtkVBox" id="vbox1">
+        <property name="visible">True</property>
+        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+        <property name="spacing">12</property>
+        <child>
+          <widget class="GtkLabel" id="info_label">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="label" translatable="yes">You are now connected to</property>
+            <property name="use_markup">True</property>
+            <property name="use_underline">True</property>
+            <property name="justify">GTK_JUSTIFY_CENTER</property>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkTable" id="users_table">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="n_rows">3</property>
+            <property name="n_columns">2</property>
+            <property name="column_spacing">6</property>
+            <property name="row_spacing">6</property>
+            <child>
+              <widget class="GtkLabel" id="label4">
+                <property name="visible">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">Video:</property>
+              </widget>
+              <packing>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
+                <property name="x_options">GTK_FILL</property>
+                <property name="x_padding">6</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkComboBox" id="video_combobox">
+                <property name="visible">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <signal name="changed" handler="video_combobox_changed_cb"/>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
+                <property name="y_options">GTK_EXPAND</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkComboBox" id="audio_combobox">
+                <property name="visible">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <signal name="changed" handler="audio_combobox_changed_cb"/>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+                <property name="y_options">GTK_EXPAND</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label3">
+                <property name="visible">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">Audio:</property>
+              </widget>
+              <packing>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+                <property name="x_options">GTK_FILL</property>
+                <property name="x_padding">6</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkAspectFrame" id="preview_aspectframe">
+                <property name="visible">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="border_width">6</property>
+                <property name="label_xalign">0</property>
+                <property name="ratio">1.3300000429153442</property>
+                <child>
+                  <widget class="GtkDrawingArea" id="preview_drawingarea">
+                    <property name="width_request">160</property>
+                    <property name="height_request">120</property>
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <signal name="expose_event" handler="exposed"/>
+                  </widget>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="frame_label">
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="label" translatable="yes">&lt;b&gt;User&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                  </widget>
+                  <packing>
+                    <property name="type">label_item</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="right_attach">2</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkHButtonBox" id="hbuttonbox1">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="spacing">6</property>
+            <property name="layout_style">GTK_BUTTONBOX_EDGE</property>
+            <child>
+              <widget class="GtkButton" id="dtmf_button">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">DTMF</property>
+                <property name="response_id">0</property>
+                <signal name="clicked" handler="show_dtmf"/>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkButton" id="button2">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="has_focus">True</property>
+                <property name="is_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">gtk-quit</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">-4</property>
+                <signal name="clicked" handler="shutdown"/>
+              </widget>
+              <packing>
+                <property name="pack_type">GTK_PACK_END</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+  <widget class="GtkWindow" id="window1">
+    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+    <child>
+      <widget class="GtkAspectFrame" id="user_frame">
+        <property name="visible">True</property>
+        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+        <property name="border_width">6</property>
+        <property name="label_xalign">0</property>
+        <property name="ratio">1.3300000429153442</property>
+        <child>
+          <widget class="GtkDrawingArea" id="user_drawingarea">
+            <property name="width_request">160</property>
+            <property name="height_request">120</property>
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <signal name="expose_event" handler="exposed"/>
+          </widget>
+        </child>
+        <child>
+          <widget class="GtkLabel" id="frame_label">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="label" translatable="yes">&lt;b&gt;User&lt;/b&gt;</property>
+            <property name="use_markup">True</property>
+          </widget>
+          <packing>
+            <property name="type">label_item</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+  <widget class="GtkDialog" id="neworconnect_dialog">
+    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+    <property name="border_width">5</property>
+    <property name="resizable">False</property>
+    <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
+    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+    <property name="has_separator">False</property>
+    <signal name="close" handler="quit"/>
+    <signal name="destroy" handler="quit"/>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox2">
+        <property name="visible">True</property>
+        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+        <property name="spacing">2</property>
+        <child>
+          <widget class="GtkTable" id="table3">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="border_width">6</property>
+            <property name="n_rows">3</property>
+            <property name="n_columns">3</property>
+            <property name="column_spacing">12</property>
+            <property name="row_spacing">12</property>
+            <child>
+              <widget class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+              </widget>
+              <packing>
+                <property name="left_attach">2</property>
+                <property name="right_attach">3</property>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkImage" id="image5">
+                <property name="visible">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="yalign">0</property>
+                <property name="icon_size">6</property>
+                <property name="icon_name">start-here</property>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkEntry" id="newip_entry">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="text" translatable="yes">127.0.0.1</property>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">3</property>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+                <property name="y_options">GTK_FILL</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label9">
+                <property name="visible">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">Port: </property>
+              </widget>
+              <packing>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
+                <property name="y_options">GTK_FILL</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label10">
+                <property name="visible">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">IP address: </property>
+              </widget>
+              <packing>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+                <property name="y_options">GTK_FILL</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label11">
+                <property name="visible">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">Enter the IP address and the port of the server to connect to, or only the port if you want to start a new server</property>
+                <property name="wrap">True</property>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">3</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkSpinButton" id="newport_spinbutton">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="max_length">5</property>
+                <property name="width_chars">5</property>
+                <property name="adjustment">9392 0 65535 1 10 10</property>
+                <property name="snap_to_ticks">True</property>
+                <property name="numeric">True</property>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
+                <property name="x_options">GTK_SHRINK</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area2">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="layout_style">GTK_BUTTONBOX_END</property>
+            <child>
+              <widget class="GtkButton" id="button7">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">gtk-close</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">-4</property>
+                <signal name="clicked" handler="quit"/>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkButton" id="button6">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="response_id">2</property>
+                <signal name="clicked" handler="new_server"/>
+                <child>
+                  <widget class="GtkHBox" id="hbox3">
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <child>
+                      <widget class="GtkImage" id="image3">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="stock">gtk-new</property>
+                      </widget>
+                      <packing>
+                        <property name="expand">False</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label5">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="label" translatable="yes">_New server</property>
+                        <property name="use_underline">True</property>
+                      </widget>
+                      <packing>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="button5">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">gtk-connect</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">1</property>
+                <signal name="clicked" handler="connect"/>
+              </widget>
+              <packing>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">GTK_PACK_END</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+  <widget class="GtkWindow" id="dtmf_window">
+    <property name="visible">True</property>
+    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+    <property name="title" translatable="yes">Send DTMF</property>
+    <child>
+      <widget class="GtkVBox" id="vbox2">
+        <property name="visible">True</property>
+        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+        <property name="spacing">12</property>
+        <child>
+          <widget class="GtkVBox" id="vbox3">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <child>
+              <widget class="GtkLabel" id="label2">
+                <property name="visible">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">Send DTMF as:</property>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkRadioButton" id="dtmf_as_event">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">RFC-4733 DTMF Event </property>
+                <property name="response_id">0</property>
+                <property name="active">True</property>
+                <property name="draw_indicator">True</property>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkRadioButton" id="dtmf_as_sound">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">Sound</property>
+                <property name="response_id">0</property>
+                <property name="draw_indicator">True</property>
+                <property name="group">dtmf_as_event</property>
+              </widget>
+              <packing>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="padding">6</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkTable" id="table1">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="n_rows">4</property>
+            <property name="n_columns">3</property>
+            <property name="column_spacing">6</property>
+            <property name="row_spacing">6</property>
+            <child>
+              <widget class="GtkButton" id="dtmf_pound">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">#</property>
+                <property name="response_id">0</property>
+                <signal name="pressed" handler="dtmf_start" object="#"/>
+                <signal name="released" handler="dtmf_stop" object="#"/>
+              </widget>
+              <packing>
+                <property name="left_attach">2</property>
+                <property name="right_attach">3</property>
+                <property name="top_attach">3</property>
+                <property name="bottom_attach">4</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="dtmf_0">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">0</property>
+                <property name="response_id">0</property>
+                <signal name="pressed" handler="dtmf_start" object="0"/>
+                <signal name="released" handler="dtmf_stop" object="0"/>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+                <property name="top_attach">3</property>
+                <property name="bottom_attach">4</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="dtmf_star">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">*</property>
+                <property name="response_id">0</property>
+                <signal name="pressed" handler="dtmf_start" object="*"/>
+                <signal name="released" handler="dtmf_stop" object="*"/>
+              </widget>
+              <packing>
+                <property name="top_attach">3</property>
+                <property name="bottom_attach">4</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="dtmf_9">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">9</property>
+                <property name="response_id">0</property>
+                <signal name="pressed" handler="dtmf_start" object="9"/>
+                <signal name="released" handler="dtmf_stop" object="9"/>
+              </widget>
+              <packing>
+                <property name="left_attach">2</property>
+                <property name="right_attach">3</property>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="dtmf_8">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">8</property>
+                <property name="response_id">0</property>
+                <signal name="pressed" handler="dtmf_start" object="8"/>
+                <signal name="released" handler="dtmf_stop" object="8"/>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="dtmf_7">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">7</property>
+                <property name="response_id">0</property>
+                <signal name="pressed" handler="dtmf_start" object="7"/>
+                <signal name="released" handler="dtmf_stop" object="7"/>
+              </widget>
+              <packing>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="dtmf_6">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">6</property>
+                <property name="response_id">0</property>
+                <signal name="pressed" handler="dtmf_start" object="6"/>
+                <signal name="released" handler="dtmf_stop" object="6"/>
+              </widget>
+              <packing>
+                <property name="left_attach">2</property>
+                <property name="right_attach">3</property>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="dtmf_5">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">5</property>
+                <property name="response_id">0</property>
+                <signal name="pressed" handler="dtmf_start" object="5"/>
+                <signal name="released" handler="dtmf_stop" object="5"/>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="dtmf_4">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">4</property>
+                <property name="response_id">0</property>
+                <signal name="pressed" handler="dtmf_start" object="4"/>
+                <signal name="released" handler="dtmf_stop" object="4"/>
+              </widget>
+              <packing>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="dtmf_3">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">3</property>
+                <property name="response_id">0</property>
+                <signal name="pressed" handler="dtmf_start" object="3"/>
+                <signal name="released" handler="dtmf_stop" object="3"/>
+              </widget>
+              <packing>
+                <property name="left_attach">2</property>
+                <property name="right_attach">3</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="dtmf_2">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">2</property>
+                <property name="response_id">0</property>
+                <signal name="pressed" handler="dtmf_start" object="2"/>
+                <signal name="released" handler="dtmf_stop" object="2"/>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="dtmf_1">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">1</property>
+                <property name="response_id">0</property>
+                <signal name="pressed" handler="dtmf_start" object="1"/>
+                <signal name="released" handler="dtmf_stop" object="1"/>
+              </widget>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkHBox" id="hbox1">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="spacing">6</property>
+            <child>
+              <widget class="GtkButton" id="button1">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">gtk-close</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">0</property>
+                <signal name="clicked" handler="dtmf_destroy"/>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="padding">6</property>
+                <property name="pack_type">GTK_PACK_END</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="padding">6</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+</glade-interface>
diff --git a/examples/gui/fs2-gui.py b/examples/gui/fs2-gui.py
new file mode 100755
index 0000000..f744618
--- /dev/null
+++ b/examples/gui/fs2-gui.py
@@ -0,0 +1,929 @@
+#!/usr/bin/python
+
+# Farsight 2 demo GUI program
+#
+# Copyright (C) 2007 Collabora, Nokia
+# @author: Olivier Crete <olivier.crete at collabora.co.uk>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+#
+
+import sys, os, pwd, os.path
+import socket
+import threading
+import weakref
+
+import signal
+
+try:
+    import pygtk
+    pygtk.require("2.0")
+
+    import gtk, gtk.glade, gobject, gtk.gdk
+    import gobject
+except ImportError, e:
+    raise SystemExit("PyGTK couldn't be found ! (%s)" % (e[0]))
+
+try:
+    import pygst
+    pygst.require('0.10')
+        
+    import gst
+except ImportError, e:
+    raise SystemExit("Gst-Python couldn't be found! (%s)" % (e[0]))
+try:
+    import farsight
+except:
+    try:
+        sys.path.append(os.path.join(os.path.dirname(__file__),
+                                     '..', '..', 'python', '.libs'))
+        import farsight
+    except ImportError, e:
+        raise SystemExit("Farsight couldn't be found! (%s)" % (e[0]))
+
+
+
+from fs2_gui_net import  FsUIClient, FsUIListener, FsUIServer
+
+CAMERA=False
+
+AUDIO=True
+VIDEO=True
+
+CLIENT=1
+SERVER=2
+
+TRANSMITTER="rawudp"
+
+mycname = "".join((pwd.getpwuid(os.getuid())[0],
+                   "-" ,
+                   str(os.getpid()),
+                   "@",
+                   socket.gethostname()))
+
+gladefile = os.path.join(os.path.dirname(__file__),"fs2-gui.glade")
+
+
+def make_video_sink(pipeline, xid, name, async=True):
+    "Make a bin with a video sink in it, that will be displayed on xid."
+    bin = gst.Bin("videosink_%d" % xid)
+    sink = gst.element_factory_make("ximagesink", name)
+    sink.set_property("sync", async)
+    sink.set_property("async", async)
+    bin.add(sink)
+    colorspace = gst.element_factory_make("ffmpegcolorspace")
+    bin.add(colorspace)
+    videoscale = gst.element_factory_make("videoscale")
+    bin.add(videoscale)
+    videoscale.link(colorspace)
+    colorspace.link(sink)
+    bin.add_pad(gst.GhostPad("sink", videoscale.get_pad("sink")))
+    sink.set_data("xid", xid)
+    return bin
+
+
+class FsUIPipeline:
+    "Object to wrap the GstPipeline"
+
+    def int_handler(self, sig, frame):
+        try:
+            gst.DEBUG_BIN_TO_DOT_FILE(self.pipeline, 0, "pipelinedump")
+        except:
+            pass
+        sys.exit(2)
+    
+    def __init__(self, elementname="fsrtpconference"):
+        self.pipeline = gst.Pipeline()
+        signal.signal(signal.SIGINT, self.int_handler)
+        notifier = farsight.ElementAddedNotifier()
+        notifier.connect("element-added", self.element_added_cb)
+        notifier.add(self.pipeline)
+        self.pipeline.get_bus().set_sync_handler(self.sync_handler)
+        self.pipeline.get_bus().add_watch(self.async_handler)
+        self.conf = gst.element_factory_make(elementname)
+        # Sets lets our own cname
+        self.conf.set_property("sdes-cname", mycname)
+        self.pipeline.add(self.conf)
+        if VIDEO:
+            self.videosource = FsUIVideoSource(self.pipeline)
+            self.videosession = FsUISession(self.conf, self.videosource)
+        if AUDIO:
+            self.audiosource = FsUIAudioSource(self.pipeline)
+            self.audiosession = FsUISession(self.conf, self.audiosource)
+            self.adder = None
+        self.pipeline.set_state(gst.STATE_PLAYING)
+
+    def __del__(self):
+        self.pipeline.set_state(gst.STATE_NULL)
+
+    def sync_handler(self, bus, message):
+        "Message handler to get the prepare-xwindow-id event"
+        if message.type == gst.MESSAGE_ELEMENT and \
+               message.structure.has_name("prepare-xwindow-id"):
+            xid = None
+            element = message.src
+            # We stored the XID on the element or its parent on the expose event
+            # Now lets look it up
+            while not xid and element:
+                xid = element.get_data("xid")
+                element = element.get_parent()
+            if xid:
+                message.src.set_xwindow_id(xid)
+                return gst.BUS_DROP
+        return gst.BUS_PASS
+
+    def async_handler(self, bus, message):
+        "Async handler to print messages"
+        if message.type == gst.MESSAGE_ERROR:
+            print message.src.get_name(), ": ", message.parse_error()
+        elif message.type == gst.MESSAGE_WARNING:
+            print message.src.get_name(), ": ", message.parse_warning()
+        elif message.type == gst.MESSAGE_ELEMENT:
+            if message.structure.has_name("dtmf-event"):
+                print "dtmf-event: %d" % message.structure["number"]
+            elif message.structure.has_name("farsight-local-candidates-prepared"):
+                message.structure["stream"].uistream.local_candidates_prepared()
+
+            elif message.structure.has_name("farsight-new-local-candidate"):
+                message.structure["stream"].uistream.new_local_candidate(
+                    message.structure["candidate"])
+            elif message.structure.has_name("farsight-codecs-changed"):
+                print message.src.get_name(), ": ", message.structure.get_name()
+                message.structure["session"].uisession.codecs_changed()
+                if AUDIO and message.structure["session"] == self.audiosession.fssession:
+                    self.codecs_changed_audio()
+                if VIDEO and  message.structure["session"] == self.videosession.fssession:
+                    self.codecs_changed_video()
+            elif message.structure.has_name("farsight-send-codec-changed"):
+                print message.src.get_name(), ": ", message.structure.get_name()
+                print "send codec changed: " + message.structure["codec"].to_string()
+                if AUDIO and message.structure["session"] == self.audiosession.fssession:
+                    self.codecs_changed_audio()
+                if VIDEO and message.structure["session"] == self.videosession.fssession:
+                    self.codecs_changed_video()
+            elif message.structure.has_name("farsight-recv-codecs-changed"):
+                print message.src.get_name(), ": ", message.structure.get_name()
+                message.structure["stream"].uistream.recv_codecs_changed( \
+                    message.structure["codecs"])
+                
+                
+            elif message.structure.has_name("farsight-error"):
+                print "Async error ("+ str(message.structure["error-no"]) +"): " + message.structure["error-msg"] +" --- "+ message.structure["debug-msg"]
+            else:
+                print message.src.get_name(), ": ", message.structure.get_name()
+        elif message.type != gst.MESSAGE_STATE_CHANGED \
+                 and message.type != gst.MESSAGE_ASYNC_DONE:
+            print message.type
+        
+        return True
+
+    def make_video_preview(self, xid, newsize_callback):
+        "Creates the preview sink"
+        self.previewsink = make_video_sink(self.pipeline, xid,
+                                           "previewvideosink", False)
+        self.pipeline.add(self.previewsink)
+        #Add a probe to wait for the first buffer to find the image size
+        self.havesize = self.previewsink.get_pad("sink").add_buffer_probe(self.have_size,
+                                                          newsize_callback)
+                                                          
+        self.previewsink.set_state(gst.STATE_PLAYING)
+        self.videosource.tee.link(self.previewsink)
+        self.pipeline.set_state(gst.STATE_PLAYING)
+        return self.previewsink
+
+    def have_size(self, pad, buffer, callback):
+        "Callback on the first buffer to know the drawingarea size"
+        x = buffer.caps[0]["width"]
+        y = buffer.caps[0]["height"]
+        callback(x,y)
+        self.previewsink.get_pad("sink").remove_buffer_probe(self.havesize)
+        return True
+
+    def link_audio_sink(self, pad):
+        "Link the audio sink to the pad"
+        print >>sys.stderr, "LINKING AUDIO SINK"
+        if not self.adder:
+            audiosink = gst.element_factory_make("alsasink")
+            audiosink.set_property("buffer-time", 50000)
+            self.pipeline.add(audiosink)
+
+            try:
+                self.adder = gst.element_factory_make("liveadder")
+            except gst.ElementNotFoundError:
+                audiosink.set_state(gst.STATE_PLAYING)
+                pad.link(audiosink.get_pad("sink"))
+                return
+            self.pipeline.add(self.adder)
+            audiosink.set_state(gst.STATE_PLAYING)
+            self.adder.link(audiosink)
+            self.adder.set_state(gst.STATE_PLAYING)
+        convert1 = gst.element_factory_make("audioconvert")
+        self.pipeline.add(convert1)
+        resample = gst.element_factory_make("audioresample")
+        self.pipeline.add(resample)
+        convert2 = gst.element_factory_make("audioconvert")
+        self.pipeline.add(convert2)
+        convert1.link(resample)
+        resample.link(convert2)
+        convert2.link(self.adder)
+        pad.link(convert1.get_pad("sink"))
+        convert2.set_state(gst.STATE_PLAYING)
+        resample.set_state(gst.STATE_PLAYING)
+        convert1.set_state(gst.STATE_PLAYING)
+
+    def element_added_cb(self, notifier, bin, element):
+        if element.get_factory().get_name() == "x264enc":
+            element.set_property("byte-stream", True)
+            element.set_property("bitrate", 128)
+        elif element.get_factory().get_name() == "gstrtpbin":
+            element.set_property("latency", 100)
+            
+
+class FsUISource:
+    "An abstract generic class for media sources"
+
+    def __init__(self, pipeline):
+        self.pipeline = pipeline
+        self.tee = gst.element_factory_make("tee")
+        pipeline.add(self.tee)
+        self.tee.set_state(gst.STATE_PLAYING)
+
+        self.source = self.make_source()
+        pipeline.add(self.source)
+        self.source.link(self.tee)
+        self.playcount = 0
+
+    def __del__(self):
+        self.source.set_state(gst.STATE_NULL)
+        self.tee.set_state(gst.STATE_NULL)
+        self.pipeline.remove(self.source)
+        self.pipeline.remove(self.tee)
+        
+        
+    def make_source(self):
+        "Creates and returns the source GstElement"
+        raise NotImplementedError()
+
+
+    def get_type(self):
+        "Returns the FsMediaType of the source."
+        raise NotImplementedError()
+
+    def get_src_pad(self, name="src%d"):
+        "Gets a source pad from the source"
+        queue = gst.element_factory_make("queue")
+        queue.set_property("leaky", 2)
+        queue.set_property("max-size-time", 50*gst.MSECOND)
+        requestpad = self.tee.get_request_pad(name)
+        self.pipeline.add(queue)
+        requestpad.link(queue.get_static_pad("sink"))
+        pad = queue.get_static_pad("src")
+        pad.set_data("requestpad", requestpad)
+        pad.set_data("queue", queue)
+        return pad
+
+    def put_src_pad(self, pad):
+        "Puts the source pad from the source"
+        self.pipeline.remove(pad.get_data("queue"))
+        self.tee.release_request_pad(pad.get_data("requestpad"))
+    
+
+class FsUIVideoSource(FsUISource):
+    "A Video source"
+    
+    def get_type(self):
+        return farsight.MEDIA_TYPE_VIDEO
+
+    def make_source(self):
+        bin = gst.Bin()
+        if CAMERA:
+            source = gst.element_factory_make("v4l2src")
+            source.set_property("device", CAMERA)
+            bin.add(source)
+        else:
+            source = gst.element_factory_make("videotestsrc")
+            source.set_property("is-live", 1)
+            bin.add(source)
+            overlay = gst.element_factory_make("timeoverlay")
+            overlay.set_property("font-desc", "Sans 32")
+            bin.add(overlay)
+            source.link(overlay)
+            source=overlay
+
+        filter = gst.element_factory_make("capsfilter")
+        filter.set_property("caps", gst.Caps("video/x-raw-yuv , width=[300,500] , height=[200,500], framerate=[20/1,30/1]"))
+        bin.add(filter)
+        source.link(filter)
+
+        videoscale = gst.element_factory_make("videoscale")
+        bin.add(videoscale)
+        filter.link(videoscale)
+
+        bin.add_pad(gst.GhostPad("src", videoscale.get_pad("src")))
+        return bin
+            
+      
+
+class FsUIAudioSource(FsUISource):
+    "An audio source"
+
+    def get_type(self):
+        return farsight.MEDIA_TYPE_AUDIO
+
+    def make_source(self):
+        source = gst.element_factory_make("audiotestsrc")
+        source.set_property("is-live", True)
+        source.set_property("wave", 5)
+        return source
+        #return gst.element_factory_make("alsasrc")
+        #return gst.element_factory_make("gconfaudiosrc")
+
+
+
+class FsUISession:
+    "This is one session (audio or video depending on the source)"
+    
+    def __init__(self, conference, source):
+        self.conference = conference
+        self.source = source
+        self.streams = []
+        self.fssession = conference.new_session(source.get_type())
+        self.fssession.uisession = self
+        if source.get_type() == farsight.MEDIA_TYPE_VIDEO:
+            # We prefer H263-1998 because we know it works
+            # We don't know if the others do work
+            # We know H264 doesn't work for now or anything else
+            # that needs to send config data
+            self.fssession.set_codec_preferences( [ \
+                farsight.Codec(farsight.CODEC_ID_ANY,
+                               "THEORA",
+                               farsight.MEDIA_TYPE_VIDEO,
+                               90000),
+                farsight.Codec(farsight.CODEC_ID_ANY,
+                               "H264",
+                               farsight.MEDIA_TYPE_VIDEO,
+                               0),
+                farsight.Codec(farsight.CODEC_ID_ANY,
+                               "H263-1998",
+                               farsight.MEDIA_TYPE_VIDEO,
+                               0),
+                farsight.Codec(farsight.CODEC_ID_ANY,
+                               "H263",
+                               farsight.MEDIA_TYPE_VIDEO,
+                               0)
+                ])
+        elif source.get_type() == farsight.MEDIA_TYPE_AUDIO:
+            self.fssession.set_codec_preferences( [ \
+                farsight.Codec(farsight.CODEC_ID_ANY,
+                               "PCMA",
+                               farsight.MEDIA_TYPE_AUDIO,
+                               0),
+                farsight.Codec(farsight.CODEC_ID_ANY,
+                               "PCMU",
+                               farsight.MEDIA_TYPE_AUDIO,
+                               0),
+                # The gst speexenc element breaks timestamps
+                farsight.Codec(farsight.CODEC_ID_DISABLE,
+                               "SPEEX",
+                               farsight.MEDIA_TYPE_AUDIO,
+                               16000),
+                # Sadly, vorbis is not currently compatible with live streaming :-(
+                farsight.Codec(farsight.CODEC_ID_DISABLE,
+                               "VORBIS",
+                               farsight.MEDIA_TYPE_AUDIO,
+                               0),
+                ])
+
+        self.sourcepad = self.source.get_src_pad()
+        self.sourcepad.link(self.fssession.get_property("sink-pad"))
+
+    def __del__(self):
+        self.sourcepad(unlink)
+        self.source.put_src_pad(self.sourcepad)
+    def __stream_finalized(self, s):
+        self.streams.remove(s)
+            
+    def new_stream(self, id, participant):
+        "Creates a new stream for a specific participant"
+        transmitter_params = {}
+        # If its video, we start at port 9078, to make it more easy
+        # to differentiate it in a tcpdump log
+        if self.source.get_type() == farsight.MEDIA_TYPE_VIDEO and \
+               TRANSMITTER == "rawudp":
+            cand = farsight.Candidate()
+            cand.component_id = farsight.COMPONENT_RTP
+            cand.port = 9078
+            transmitter_params["preferred-local-candidates"] = [cand]
+        realstream = self.fssession.new_stream(participant.fsparticipant,
+                                             farsight.DIRECTION_BOTH,
+                                             TRANSMITTER, transmitter_params)
+        stream = FsUIStream(id, self, participant, realstream)
+        self.streams.append(weakref.ref(stream, self.__stream_finalized))
+        return stream
+
+    def dtmf_start(self, event, method):
+        if (event == "*"):
+            event = farsight.DTMF_EVENT_STAR
+        elif (event == "#"):
+            event = farsight.DTMF_EVENT_POUND
+        else:
+            event = int(event)
+        self.fssession.start_telephony_event(event, 2, method)
+        
+    def dtmf_stop(self, method):
+        self.fssession.stop_telephony_event(method)
+
+    def codecs_changed(self):
+        "Callback from FsSession"
+        for s in self.streams:
+            try:
+                s().codecs_changed()
+            except AttributeError:
+                pass
+
+    def send_stream_codecs(self, codecs, sourcestream):
+        for s in self.streams:
+            stream = s()
+            if stream and stream is not sourcestream:
+                stream.connect.send_codecs(stream.participant.id,
+                                           sourcestream.id,
+                                           codecs,
+                                           sourcestream.participant.id)
+
+class FsUIStream:
+    "One participant in one session"
+
+    def __init__(self, id, session, participant, fsstream):
+        self.id = id
+        self.session = session
+        self.participant = participant
+        self.fsstream = fsstream
+        self.connect = participant.connect
+        self.fsstream.uistream = self
+        self.fsstream.connect("src-pad-added", self.__src_pad_added)
+        self.send_codecs = False
+        self.last_codecs = None
+        self.last_stream_codecs = None
+        self.candidates = []
+
+    def local_candidates_prepared(self):
+        "Callback from FsStream"
+        self.connect.send_candidates_done(self.participant.id, self.id)
+    def new_local_candidate(self, candidate):
+        "Callback from FsStream"
+        self.connect.send_candidate(self.participant.id, self.id, candidate)
+    def __src_pad_added(self, stream, pad, codec):
+        "Callback from FsStream"
+        if self.session.source.get_type() == farsight.MEDIA_TYPE_VIDEO:
+            self.participant.link_video_sink(pad)
+        else:
+            self.participant.pipeline.link_audio_sink(pad)
+
+    def candidate(self, candidate):
+        "Callback for the network object."
+        self.candidates.append(candidate)
+    def candidates_done(self):
+        "Callback for the network object."
+        self.fsstream.set_remote_candidates(self.candidates)
+        self.candidates = []
+    def codecs(self, codecs):
+        "Callback for the network object. Set the codecs"
+
+        print "Remote codecs"
+        for c in codecs:
+            print "Got remote codec from %s/%s %s" % \
+                  (self.participant.id, self.id, c.to_string())
+        oldcodecs = self.fsstream.get_property("remote-codecs")
+        if oldcodecs == codecs:
+            return
+        try:
+            self.fsstream.set_remote_codecs(codecs)
+        except AttributeError:
+            print "Tried to set codecs with 0 codec"
+        self.send_local_codecs()
+        self.send_stream_codecs()
+
+
+    def send_local_codecs(self):
+        "Callback for the network object."
+        self.send_codecs = True
+        self.check_send_local_codecs()
+
+    def codecs_changed(self):
+        self.check_send_local_codecs()
+        self.send_stream_codecs()
+
+    def check_send_local_codecs(self):
+        "Internal function to send our local codecs when they're ready"
+        if not self.send_codecs:
+            return
+        if not self.session.fssession.get_property("codecs-ready"):
+            print "Codecs are not ready"
+            return
+        codecs = self.session.fssession.get_property("codecs")
+        assert(codecs is not None and len(codecs) > 0)
+        if (codecs == self.last_codecs):
+            return
+        self.last_codecs = codecs
+        print "sending local codecs"
+        self.connect.send_codecs(self.participant.id, self.id, codecs)
+
+    def send_stream_codecs(self):
+        if not self.connect.is_server:
+            return
+        if not self.session.fssession.get_property("codecs-ready"):
+            return
+        codecs = self.fsstream.get_property("negotiated-codecs")
+        if codecs:
+            self.session.send_stream_codecs(codecs, self)
+
+    def recv_codecs_changed(self, codecs):
+        self.participant.recv_codecs_changed()
+
+
+    def __remove_from_send_codecs_to(self, participant):
+        self.send_codecs_to.remote(participant)
+
+
+    def send_codecs_to(self, participant):
+        codecs = self.fsstream.get_property("negotiated-codecs")
+        print "sending stream %s codecs from %s to %s" % \
+              (self.id, self.participant.id, participant.id)
+        if codecs:
+            participant.connect.send_codecs(participant.id, self.id, codecs,
+                                            self.participant.id)            
+
+
+class FsUIParticipant:
+    "Wraps one FsParticipant, is one user remote contact"
+    
+    def __init__(self, connect, id, cname, pipeline, mainui):
+        self.connect = connect
+        self.id = id
+        self.cname = cname
+        self.pipeline = pipeline
+        self.mainui = mainui
+        self.fsparticipant = pipeline.conf.new_participant(cname)
+        self.outcv = threading.Condition()
+        self.funnel = None
+        self.make_widget()
+        self.streams = {}
+        if VIDEO:
+            self.streams[int(farsight.MEDIA_TYPE_VIDEO)] = \
+              pipeline.videosession.new_stream(
+                int(farsight.MEDIA_TYPE_VIDEO), self)
+        if AUDIO:
+            self.streams[int(farsight.MEDIA_TYPE_AUDIO)] = \
+              pipeline.audiosession.new_stream(
+                int(farsight.MEDIA_TYPE_AUDIO), self)
+        
+    def candidate(self, media, candidate):
+        "Callback for the network object."
+        self.streams[media].candidate(candidate)
+    def candidates_done(self, media):
+        "Callback for the network object."
+        self.streams[media].candidates_done()
+    def codecs(self, media, codecs):
+        "Callback for the network object."
+        self.streams[media].codecs(codecs)
+    def send_local_codecs(self):
+        "Callback for the network object."
+        for id in self.streams:
+            self.streams[id].send_local_codecs()
+
+    def make_widget(self):
+        "Make the widget of the participant's video stream."
+        gtk.gdk.threads_enter()
+        self.glade = gtk.glade.XML(gladefile, "user_frame")
+        self.userframe = self.glade.get_widget("user_frame")
+        self.glade.get_widget("frame_label").set_text(self.cname)
+        self.glade.signal_autoconnect(self)
+        self.label = gtk.Label()
+        self.label.set_alignment(0,0)
+        self.label.show()
+        self.mainui.hbox_add(self.userframe, self.label)
+        gtk.gdk.threads_leave()
+
+    def exposed(self, widget, *args):
+        """From the exposed signal, used to create the video sink
+        The video sink will be created here, but will only be linked when the
+        pad arrives and link_video_sink() is called.
+        """
+        if not VIDEO:
+            return
+        try:
+            self.videosink.get_by_interface(gst.interfaces.XOverlay).expose()
+        except AttributeError:
+            try:
+                self.outcv.acquire()
+                self.videosink = make_video_sink(self.pipeline.pipeline,
+                                                 widget.window.xid,
+                                                 "uservideosink")
+                self.pipeline.pipeline.add(self.videosink)
+                self.funnel = gst.element_factory_make("fsfunnel")
+                self.pipeline.pipeline.add(self.funnel)
+                self.funnel.link(self.videosink)
+                self.havesize = self.videosink.get_pad("sink").add_buffer_probe(self.have_size)
+
+                self.videosink.set_state(gst.STATE_PLAYING)
+                self.funnel.set_state(gst.STATE_PLAYING)
+                self.outcv.notifyAll()
+            finally:
+                self.outcv.release()
+            
+
+    def have_size(self, pad, buffer):
+        "Callback on the first buffer to know the drawingarea size"
+        x = buffer.caps[0]["width"]
+        y = buffer.caps[0]["height"]
+        gtk.gdk.threads_enter()
+        self.glade.get_widget("user_drawingarea").set_size_request(x,y)
+        gtk.gdk.threads_leave()
+        self.videosink.get_pad("sink").remove_buffer_probe(self.havesize)
+        del self.havesize
+        return True
+                 
+
+
+    def link_video_sink(self, pad):
+        """Link the video sink
+
+        Wait for the funnnel for the video sink to be created, when it has been
+        created, link it.
+        """
+        try:
+            self.outcv.acquire()
+            while self.funnel is None:
+                self.outcv.wait()
+            print >>sys.stderr, "LINKING VIDEO SINK"
+            pad.link(self.funnel.get_pad("sink%d"))
+        finally:
+            self.outcv.release()
+
+    def destroy(self):
+        if VIDEO:
+            try:
+                self.videosink.get_pad("sink").disconnect_handler(self.havesize)
+                pass
+            except AttributeError:
+                pass
+            self.glade.get_widget("user_drawingarea").disconnect_by_func(self.exposed)
+            self.streams = {}
+            self.outcv.acquire()
+            self.videosink.set_locked_state(True)
+            self.funnel.set_locked_state(True)
+            self.videosink.set_state(gst.STATE_NULL)
+            self.funnel.set_state(gst.STATE_NULL)
+            self.pipeline.pipeline.remove(self.videosink)
+            self.pipeline.pipeline.remove(self.funnel)
+            del self.videosink
+            del self.funnel
+            self.outcv.release()
+        gtk.gdk.threads_enter()
+        self.userframe.destroy()
+        self.label.destroy()
+        gtk.gdk.threads_leave()
+
+    def error(self):
+        "Callback for the network object."
+        if self.id == 1:
+            self.mainui.fatal_error("<b>Disconnected from server</b>")
+        else:
+            print "ERROR ON %d" % (self.id)
+
+    def recv_codecs_changed(self):
+        codecs = {}
+        for s in self.streams:
+            codec = self.streams[s].fsstream.get_property("current-recv-codecs")
+            mediatype = self.streams[s].session.fssession.get_property("media-type")
+            if len(codec):
+                if mediatype in codecs:
+                    codecs[mediatype] += codec
+                else:
+                    codecs[mediatype] = codec
+        str = ""
+        for mt in codecs:
+            str += "<big>" +mt.value_nick.title() + "</big>:\n"
+            for c in codecs[mt]:
+                str += "  <b>%s</b>: %s %s\n" % (c.id, 
+                                                 c.encoding_name,
+                                                 c.clock_rate)
+        self.label.set_markup(str)
+
+    def send_codecs_to(self, participant):
+        for sid in self.streams:
+            self.streams[sid].send_codecs_to(participant)
+    
+
+class FsMainUI:
+    "The main UI and its different callbacks"
+    
+    def __init__(self, mode, ip, port):
+        self.mode = mode
+        self.pipeline = FsUIPipeline()
+        self.pipeline.codecs_changed_audio = self.reset_audio_codecs
+        self.pipeline.codecs_changed_video = self.reset_video_codecs
+        self.glade = gtk.glade.XML(gladefile, "main_window")
+        self.glade.signal_autoconnect(self)
+        self.mainwindow = self.glade.get_widget("main_window")
+        self.audio_combobox = self.glade.get_widget("audio_combobox")
+        self.video_combobox = self.glade.get_widget("video_combobox")
+        liststore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
+        self.audio_combobox.set_model(liststore)
+        cell = gtk.CellRendererText()
+        self.audio_combobox.pack_start(cell, True)
+        self.audio_combobox.add_attribute(cell, 'text', 0)
+        self.reset_audio_codecs()
+        liststore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
+        self.video_combobox.set_model(liststore)
+        cell = gtk.CellRendererText()
+        self.video_combobox.pack_start(cell, True)
+        self.video_combobox.add_attribute(cell, 'text', 0)
+        self.reset_video_codecs()
+
+        if mode == CLIENT:
+            self.client = FsUIClient(ip, port, mycname, FsUIParticipant,
+                                     self.pipeline, self)
+            self.glade.get_widget("info_label").set_markup(
+                "<b>%s</b>\nConnected to %s:%s" % (mycname, ip, port))
+        elif mode == SERVER:
+            self.server = FsUIListener(port, FsUIServer, mycname,
+                                       FsUIParticipant, self.pipeline, self)
+            self.glade.get_widget("info_label").set_markup(
+                "<b>%s</b>\nExpecting connections on port %s" %
+                (mycname, self.server.port))
+
+        
+        self.mainwindow.show()
+
+    def reset_codecs(self, combobox, fssession):
+        liststore = combobox.get_model()
+        current = fssession.get_property("current-send-codec")
+        liststore.clear()
+        for c in fssession.get_property("codecs"):
+            str = ("%s: %s/%s %s" % (c.id, 
+                                     c.media_type.value_nick,
+                                     c.encoding_name,
+                                     c.clock_rate))
+            iter = liststore.append([str, c])
+            if current and c and current.id == c.id:
+                combobox.set_active_iter(iter)
+                print "active: "+ c.to_string()
+
+    def reset_audio_codecs(self):
+        if AUDIO:
+            self.reset_codecs(self.audio_combobox,
+                              self.pipeline.audiosession.fssession)
+
+    def reset_video_codecs(self):
+        if VIDEO:
+            self.reset_codecs(self.video_combobox,
+                              self.pipeline.videosession.fssession)
+
+    def combobox_changed_cb(self, combobox, fssession):
+        liststore = combobox.get_model()
+        iter = combobox.get_active_iter()
+        if iter:
+            codec = liststore.get_value(iter, 1)
+            fssession.set_send_codec(codec)
+
+    def audio_combobox_changed_cb(self, combobox):
+        self.combobox_changed_cb(combobox, self.pipeline.audiosession.fssession)
+    
+    def video_combobox_changed_cb(self, combobox):
+        self.combobox_changed_cb(combobox, self.pipeline.videosession.fssession)
+        
+        
+    def exposed(self, widget, *args):
+        "Callback from the exposed event of the widget to make the preview sink"
+        if not VIDEO:
+            return
+        try:
+            self.preview.get_by_interface(gst.interfaces.XOverlay).expose()
+        except AttributeError:
+            self.preview = self.pipeline.make_video_preview(widget.window.xid,
+                                                            self.newsize)
+
+    def newsize (self, x, y):
+        self.glade.get_widget("preview_drawingarea").set_size_request(x,y)
+        
+    def shutdown(self, widget=None):
+        gtk.main_quit()
+        
+    def hbox_add(self, widget, label):
+        table = self.glade.get_widget("users_table")
+        x = table.get_properties("n-columns")[0]
+        table.attach(widget, x, x+1, 0, 1)
+        table.attach(label, x, x+1, 1, 3, xpadding=6)
+
+    def __del__(self):
+        self.mainwindow.destroy()
+
+    def fatal_error(self, errormsg):
+        gtk.gdk.threads_enter()
+        dialog = gtk.MessageDialog(self.mainwindow,
+                                   gtk.DIALOG_MODAL,
+                                   gtk.MESSAGE_ERROR,
+                                   gtk.BUTTONS_OK)
+        dialog.set_markup(errormsg);
+        dialog.run()
+        dialog.destroy()
+        gtk.main_quit()
+        gtk.gdk.threads_leave()
+
+    def show_dtmf(self, button):
+        try:
+            self.dtmf.present()
+        except AttributeError:
+            self.dtmf =  gtk.glade.XML(gladefile, "dtmf_window")
+            self.dtmf.signal_autoconnect(self)
+
+    def dtmf_start(self, button):
+        if (self.dtmf.get_widget("dtmf_as_event").get_active()):
+            self.dtmf_last_method = farsight.DTMF_METHOD_RTP_RFC4733
+        elif (self.dtmf.get_widget("dtmf_as_sound").get_active()):
+            self.dtmf_last_method = farsight.DTMF_METHOD_IN_BAND
+        else:
+            print "Invalid DTMF Method"
+            return
+        self.pipeline.audiosession.dtmf_start(button.get_label(), \
+                                              self.dtmf_last_method)
+                                              
+    def dtmf_stop(self, button):
+        try:
+            self.pipeline.audiosession.dtmf_stop(self.dtmf_last_method)
+            del self.dtmf_last_method
+        except AttributeError:
+            pass
+    def dtmf_destroy(self, button):
+        self.dtmf.get_widget("dtmf_window").destroy()
+        del self.dtmf
+
+
+
+class FsUIStartup:
+    "Displays the startup window and then creates the FsMainUI"
+    
+    def __init__(self):
+        self.glade = gtk.glade.XML(gladefile, "neworconnect_dialog")
+        self.dialog = self.glade.get_widget("neworconnect_dialog")
+        self.glade.get_widget("newport_spinbutton").set_value(9893)
+        self.glade.signal_autoconnect(self)
+        self.dialog.show()
+        self.acted = False
+
+    def action(self, mode):
+        port = self.glade.get_widget("newport_spinbutton").get_value_as_int()
+        ip = self.glade.get_widget("newip_entry").get_text()
+        try:
+            self.ui = FsMainUI(mode, ip, port)
+            self.acted = True
+            self.dialog.destroy()
+            del self.glade
+            del self.dialog
+        except socket.error, e:
+            dialog = gtk.MessageDialog(self.dialog,
+                                       gtk.DIALOG_MODAL,
+                                       gtk.MESSAGE_ERROR,
+                                       gtk.BUTTONS_OK)
+            dialog.set_markup("<b>Could not connect to %s %d</b>" % (ip,port))
+            dialog.format_secondary_markup(e[1])
+            dialog.run()
+            dialog.destroy()
+        
+    def new_server(self, widget):
+        self.action(SERVER)
+
+    def connect(self, widget):
+        self.action(CLIENT)
+        
+
+    def quit(self, widget):
+        if not self.acted:
+            gtk.main_quit()
+
+
+
+
+if __name__ == "__main__":
+    if len(sys.argv) >= 2:
+        CAMERA = sys.argv[1]
+    else:
+        CAMERA = None
+    
+    gobject.threads_init()
+    gtk.gdk.threads_init()
+    startup = FsUIStartup()
+    gtk.main()
diff --git a/examples/gui/fs2_gui_net.py b/examples/gui/fs2_gui_net.py
new file mode 100644
index 0000000..c834d77
--- /dev/null
+++ b/examples/gui/fs2_gui_net.py
@@ -0,0 +1,456 @@
+#!/usr/bin/python
+
+# Farsight 2 simple network signalling library for the demo GUI
+#
+# Copyright (C) 2007 Collabora, Nokia
+# @author: Olivier Crete <olivier.crete at collabora.co.uk>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+#
+
+#
+# This is the signalling code used by fs2-gui.py
+#
+
+import sys, os, pwd, os.path
+import socket, struct
+import gc
+
+
+try:
+    import pygst
+    pygst.require('0.10')
+        
+    import gst
+except ImportError, e:
+    raise SystemExit("Gst-Python couldn't be found! (%s)" % (e[0]))
+
+try:
+    import farsight
+except:
+    sys.path.append(os.path.join(os.path.dirname(__file__),
+                                 '..', '..', 'python', '.libs'))
+    import farsight
+
+import gobject
+
+class FsUIConnect:
+    ERROR = 0
+    CODECS = 1
+    CANDIDATE = 2
+    CANDIDATES_DONE = 3
+    INTRO = 4
+
+    def __reset(self):
+        self.type = None
+        self.media = None
+        self.size = struct.calcsize("!IIIIII")
+        self.data = ""
+        self.dest = -1
+        self.src = -1
+ 
+    
+    def __init__(self, sock, callbacks, myid=0):
+        self.sock = sock
+        self.__reset()
+        self.callbacks = callbacks
+        self.myid = myid
+        self.partid = 1
+        self.is_server = True
+        sock.setblocking(0)
+        gobject.io_add_watch(self.sock.fileno(), gobject.IO_IN,
+                             self.__data_in)
+        gobject.io_add_watch(self.sock.fileno(),
+                             gobject.IO_ERR | gobject.IO_HUP,
+                             self.__error)
+
+    def __error(self, source, condition):
+        print "have error"
+        if (self.src >= 0):
+            self.callbacks[self.ERROR](self.src)
+        else:
+            self.callbacks[self.ERROR](self.partid)
+        return False
+
+    def __data_in(self, source, condition):
+        data = self.sock.recv(self.size-len(self.data))
+
+        if len(data) == 0:
+            print "received nothing"
+            if (self.src >= 0):
+                self.callbacks[self.ERROR](self.src)
+            else:
+                self.callbacks[self.ERROR](self.partid)
+            return False
+        
+        self.data += data
+        if len(self.data) == self.size:
+            if self.type is not None:
+                if self.type == self.CODECS:
+                    data = self.__codecs_from_string(data)
+                elif self.type == self.CANDIDATE:
+                    data = self.__candidate_from_string(data)
+                else:
+                    data = self.data
+                self.callbacks[self.type](self.src, self.dest,
+                                          self.media, data)
+                self.__reset()
+            else:
+                (check,
+                 self.src,
+                 self.dest,
+                 self.type,
+                 self.media,
+                 self.size) = struct.unpack("!IIIIII", self.data)
+                if check != 0xDEADBEEF:
+                    print "CORRUPTION"
+                    sys.exit(1)
+                if self.myid > 1 and self.dest != self.myid:
+                    print "GOT MESSAGE FOR %d, but I am %d" % (self.dest,
+                                                               self.myid)
+                    sys.exit(1)
+                self.data=""
+                if self.size == 0:
+                    self.callbacks[self.type](self.src, self.dest,
+                                              self.media, None)
+                    self.__reset()
+        return True
+
+    def __send_data(self, dest, type, media=0, data="", src=None):
+        if src is None: src = self.myid
+        if src == 0 and type != self.INTRO: raise Exception
+        try:
+            self.sock.sendall(struct.pack("!IIIIII",
+                                          0xDEADBEEF,
+                                          int(src),
+                                          int(dest),
+                                          int(type),
+                                          int(media),
+                                          len(data)))
+            self.sock.sendall(data)
+        except socket.error:
+            print "have error"
+            self.callbacks[self.ERROR](self.partid)
+
+
+    def send_error(self, dest, src):
+        self.__send_data(dest, self.ERROR, src=src)
+    def send_intro(self, dest, cname, src=None):
+        self.__send_data(dest, self.INTRO, data=cname, src=src)
+    def send_codecs(self, dest, media, codecs, src=None):
+        self.__send_data(dest, self.CODECS,
+                         media=media,
+                         data=self.__codecs_to_string(codecs), src=src)
+    def send_candidate(self, dest, media, candidate, src=None):
+        self.__send_data(dest, self.CANDIDATE, media=media,
+                         data=self.__candidate_to_string(candidate), src=src)
+    def send_candidates_done(self, dest, media, src=None):
+        self.__send_data(dest, self.CANDIDATES_DONE, media=media, src=src)
+
+    def __del__(self):
+        try:
+            self.sock.close()
+        except AttributeError:
+            pass
+
+
+    def __candidate_to_string(self, candidate):
+        return "|".join((
+            candidate.foundation,
+            str(candidate.component_id),
+            candidate.ip,
+            str(candidate.port),
+            candidate.base_ip,
+            str(candidate.base_port),
+            str(int(candidate.proto)),
+            str(candidate.priority),
+            str(int(candidate.type)),
+            candidate.username,
+            candidate.password))
+
+    def __candidate_from_string(self, string):
+        candidate = farsight.Candidate()
+        (candidate.foundation,
+         component_id,
+         candidate.ip,
+         port,
+         candidate.base_ip,
+         base_port,
+         proto,
+         priority,
+         type,
+         candidate.username,
+         candidate.password) = string.split("|")
+        candidate.component_id = int(component_id)
+        candidate.port = int(port)
+        candidate.base_port = int(base_port)
+        candidate.proto = int(proto)
+        candidate.priority = int(priority)
+        candidate.type = int(type)
+        return candidate
+
+    def __codecs_to_string(self, codecs):
+        codec_strings = []
+        for codec in codecs:
+            start = " ".join((str(codec.id),
+                              codec.encoding_name,
+                              str(int(codec.media_type)),
+                              str(codec.clock_rate),
+                              str(codec.channels)))
+            codec = "".join((start,
+                             "|",
+                             ";".join(["=".join(i) for i in codec.optional_params])))
+            codec_strings.append(codec)
+            
+        return "\n".join(codec_strings)
+
+
+    def __codecs_from_string(self, string):
+        codecs = []
+        for substring in string.split("\n"):
+            (start,end) = substring.split("|")
+            (id, encoding_name, media_type, clock_rate, channels) = start.split(" ")
+            codec = farsight.Codec(int(id), encoding_name, int(media_type),
+                               int(clock_rate))
+            codec.channels = int(channels)
+            if len(end):
+                codec.optional_params = \
+                  [tuple(x.split("=",1)) for x in end.split(";") if len(x) > 0]
+            codecs.append(codec)
+        return codecs
+
+class FsUIConnectClient (FsUIConnect):
+    def __init__(self, ip, port, callbacks):
+        sock = socket.socket()
+        sock.connect((ip, port))
+        FsUIConnect.__init__(self, sock, callbacks)
+        self.is_server = False
+
+class FsUIListener:
+    def __init__(self, port, callback, *args):
+        self.sock = socket.socket()
+        self.callback = callback
+        self.args = args
+        bound = False
+        while not bound:
+            try:
+                self.sock.bind(("", port))
+                bound = True
+            except socket.error, e:
+                port += 1
+        self.port = port
+        print "Bound to port ", port
+        self.sock.setblocking(0)
+        gobject.io_add_watch(self.sock.fileno(), gobject.IO_IN, self.data_in)
+        gobject.io_add_watch(self.sock.fileno(),
+                             gobject.IO_ERR | gobject.IO_HUP,
+                             self.error)
+        self.sock.listen(3)
+
+    def error(self, source, condition):
+        print "Error on listen"
+        sys.exit(1)
+        return False
+
+    def data_in(self, source, condition):
+        (sock,addr) = self.sock.accept()
+        self.callback(sock, *self.args)
+        return True
+    
+class FsUIClient:
+    def __init__(self, ip, port, cname, get_participant, *args):
+        self.participants = {}
+        self.get_participant = get_participant
+        self.args = args
+        self.cname = cname
+        self.connect = FsUIConnectClient(ip, port, (self.__error,
+                                                    self.__codecs,
+                                                    self.__candidate,
+                                                    self.__candidate_done,
+                                                    self.__intro))
+        self.connect.send_intro(1, cname)
+
+    def __codecs(self, src, dest, media, data):
+        print "Got codec Src:%d dest:%d data:%s" % (src, dest, data)
+        self.participants[src].codecs(media, data)
+    def __candidate(self, src, dest, media, data):
+        self.participants[src].candidate(media, data)
+    def __candidate_done(self, src, dest, media, data):
+        self.participants[src].candidates_done(media)
+    def __intro(self, src, dest, media, cname):
+        print "Got Intro from %s, I am %d" % (src, dest)
+        if src == 1:
+            self.connect.myid = dest
+        if not self.participants.has_key(src):
+            if src != 1:
+                self.connect.send_intro(src, self.cname)
+            self.participants[src] = self.get_participant(self.connect, src,
+                                                          cname,
+                                                          *self.args)
+    def __error(self, participantid, *arg):
+        print "Client Error", participantid
+        if participantid == 1:
+            # Communication error with server, its over
+            self.participants[participantid].error()
+        else:
+            self.participants[participantid].destroy()
+            del self.participants[participantid]
+            gc.collect()
+
+
+class FsUIServer:
+    nextid = 2
+    participants = {}
+
+    def __init__(self, sock, cname, get_participant, *args):
+        self.cname = cname
+        self.get_participant = get_participant
+        self.args = args
+        self.connect = FsUIConnect(sock, (self.__error,
+                                          self.__codecs,
+                                          self.__candidate,
+                                          self.__candidate_done,
+                                          self.__intro), 1)
+    def __codecs(self, src, dest, media, data):
+        FsUIServer.participants[src].codecs(media, data)
+    def __candidate(self, src, dest, media, data):
+        if dest == 1:
+            FsUIServer.participants[src].candidate(media, data)
+        else:
+            print data
+            FsUIServer.participants[dest].connect.send_candidate(dest,
+                                                                 media,
+                                                                 data,
+                                                                 src)
+    def __candidate_done(self, src, dest, media, data):
+        if dest == 1:
+            FsUIServer.participants[src].candidates_done(media)
+        else:
+            FsUIServer.participants[dest].connect.send_candidates_done(dest,
+                                                                       media,
+                                                                       src)
+    def __intro(self, src, dest, media, cname):
+        print "Got Intro from %s to %s" % (src, dest)
+        if src == 0 and dest == 1:
+            newid = FsUIServer.nextid
+            # Forward the introduction to all other participants
+            for pid in FsUIServer.participants:
+                print "Sending from %d to %d" % (newid, pid)
+                FsUIServer.participants[pid].connect.send_intro(pid, cname,
+                                                                newid)
+            self.connect.send_intro(newid, self.cname)
+            self.connect.partid = newid
+            FsUIServer.participants[newid] = self.get_participant(self.connect,
+                                                                  newid,
+                                                                  cname,
+                                                                  *self.args)
+            FsUIServer.participants[newid].send_local_codecs()
+            FsUIServer.nextid += 1
+        elif dest != 1:
+            FsUIServer.participants[dest].connect.send_intro(dest,
+                                                             cname,
+                                                             src)
+            FsUIServer.participants[src].send_codecs_to(
+                        FsUIServer.participants[dest])
+        else:
+            print "ERROR SRC != 0"
+            
+    def __error(self, participantid, *args):
+        print "Server Error", participantid
+        FsUIServer.participants[participantid].destroy()
+        del FsUIServer.participants[participantid]
+        gc.collect()
+        for pid in FsUIServer.participants:
+            FsUIServer.participants[pid].connect.send_error(pid, participantid)
+
+if __name__ == "__main__":
+    class TestMedia:
+        def __init__(self, pid, id, connect):
+            self.pid = pid
+            self.id = id
+            self.connect = connect
+            candidate = farsight.Candidate()
+            candidate.component_id = 1
+            connect.send_candidate(self.pid, self.id, candidate)
+            connect.send_candidates_done(self.pid, self.id)
+        def candidate(self, candidate):
+            print "Got candidate", candidate
+        def candidates_done(self):
+            print "Got candidate done"
+        def codecs(self, codecs):
+            if self.connect.myid != 1:
+                self.connect.send_codecs(1, self.id,
+                                        [farsight.Codec(self.connect.myid,
+                                                       "codec-name",
+                                                       self.pid,
+                                                       self.id)])
+       
+        def send_local_codecs(self):
+            print "Send local codecs to %s for media %s" % (self.pid, self.id)
+            self.connect.send_codecs(self.pid, self.id,
+                                     [farsight.Codec(self.connect.myid,
+                                                     "local_codec",
+                                                     self.pid,
+                                                     self.id)])
+        def get_codecs(self):
+            return [farsight.Codec(self.connect.myid,
+                                   "nego-codecs",
+                                   self.pid,
+                                   self.id)]
+            
+            
+    class TestParticipant:
+        def __init__(self, connect, id, cname, *args):
+            self.id = id
+            self.streams = {1: TestMedia(id, 1, connect),
+                            2: TestMedia(id, 2, connect)}
+            self.cname = cname
+            self.connect = connect
+            print "New Participant %s and cname %s" % (id,cname)
+        def candidate(self, media, candidate):
+            self.streams[media].candidate(candidate)
+        def candidates_done(self, media):
+            self.streams[media].candidates_done()
+        def codecs(self, media, codecs):
+            self.streams[media].codecs(codecs)
+        def send_local_codecs(self):
+            for id in self.streams:
+                self.streams[id].send_local_codecs()
+        def destroy(self):
+            pass
+        def send_codecs_to(self, participant):
+            for sid in self.streams:
+                print "to: %s from: %s" % (str(participant.id), (self.id))
+                participant.connect.send_codecs(participant.id,
+                                                self.streams[sid].id,
+                                                self.streams[sid].get_codecs(),
+                                                self.id)
+        def error(self):
+            print "ERROR"
+            sys.exit(1)
+        def destroy(self):
+            passs
+            
+
+    mycname = "test"
+    mainloop = gobject.MainLoop()
+    gobject.threads_init()
+    if len(sys.argv) > 1:
+        client = FsUIClient("127.0.0.1", int(sys.argv[1]),
+                            "cname" + sys.argv[1],
+                            TestParticipant)
+    else:
+        listener = FsUIListener(9893, FsUIServer, "cnameServ", TestParticipant)
+    mainloop.run()
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5a2161a..8c22271 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -4,6 +4,6 @@ if HAVE_GST_CHECK
 SUBDIRS_CHECK += check
 endif
 
-SUBDIRS = $(SUBDIRS_CHECK) rtp gui commandline
+SUBDIRS = $(SUBDIRS_CHECK) rtp
 
-DIST_SUBDIRS = check rtp gui commandline
+DIST_SUBDIRS = check rtp
diff --git a/tests/commandline/Makefile.am b/tests/commandline/Makefile.am
deleted file mode 100644
index d374e67..0000000
--- a/tests/commandline/Makefile.am
+++ /dev/null
@@ -1,14 +0,0 @@
-
-noinst_PROGRAMS = simple-call
-
-
-AM_CFLAGS = \
-	-I$(top_srcdir)/gst/fsrtpconference/ \
-	$(FS2_INTERNAL_CFLAGS) \
-	$(FS2_CFLAGS) \
-	$(GST_CFLAGS) \
-	$(CFLAGS)
-
-LDADD = \
-	$(top_builddir)/gst-libs/gst/farsight/libgstfarsight-0.10.la \
-	$(GST_LIBS) 
diff --git a/tests/commandline/simple-call.c b/tests/commandline/simple-call.c
deleted file mode 100644
index fbc56fb..0000000
--- a/tests/commandline/simple-call.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/* Farsight 2 ad-hoc test for simple calls.
- *
- * Copyright (C) 2008 Collabora, Nokia
- * @author: Olivier Crete <olivier.crete at collabora.co.uk>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-/*
- * WARNING:
- *
- * Do not use this as an example of a proper use of farsight, it assumes that
- * both ends have the EXACT same list of codec installed in the EXACT same order
- */
-
-
-#include <stdlib.h>
-
-#include <glib.h>
-#include <gst/gst.h>
-#include <gst/farsight/fs-conference-iface.h>
-
-#define DEFAULT_AUDIOSRC       "alsasrc"
-#define DEFAULT_AUDIOSINK      "audioconvert ! audioresample ! audioconvert ! alsasink"
-
-typedef struct _TestSession
-{
-  FsSession *session;
-  FsStream *stream;
-} TestSession;
-
-
-static void
-print_error (GError *error)
-{
-  if (error)
-  {
-    g_error ("Error: %s:%d : %s", g_quark_to_string (error->domain),
-        error->code, error->message);
-  }
-}
-
-static void
-src_pad_added_cb (FsStream *stream, GstPad *pad, FsCodec *codec,
-    gpointer user_data)
-{
-  GstElement *pipeline = GST_ELEMENT_CAST (user_data);
-  GstElement *sink = NULL;
-  GError *error = NULL;
-  GstPad *pad2;
-
-  g_print ("Adding receive pipeline\n");
-
-  if (g_getenv ("AUDIOSINK"))
-    sink = gst_parse_bin_from_description (g_getenv ("AUDIOSINK"), TRUE,
-        &error);
-  else
-    sink = gst_parse_bin_from_description (DEFAULT_AUDIOSINK, TRUE,
-        &error);
-  print_error (error);
-  g_assert (sink);
-
-  g_assert (gst_bin_add (GST_BIN (pipeline), sink));
-
-
-  pad2 = gst_element_get_static_pad (sink, "sink");
-  g_assert (pad2);
-
-  g_assert (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (pad, pad2)));
-
-  g_assert (gst_element_set_state (sink, GST_STATE_PLAYING) !=
-      GST_STATE_CHANGE_FAILURE);
-
-  gst_object_unref (pad2);
-}
-
-static TestSession*
-add_audio_session (GstElement *pipeline, FsConference *conf, guint id,
-    FsParticipant *part, guint localport, const gchar *remoteip,
-    guint remoteport)
-{
-  TestSession *ses = g_slice_new0 (TestSession);
-  GError *error = NULL;
-  GstPad *pad = NULL, *pad2 = NULL;
-  GstElement *src = NULL;
-  GList *cands = NULL;
-  GList *codecs = NULL;
-  GParameter param = {0};
-  gboolean res;
-
-  ses->session = fs_conference_new_session (conf, FS_MEDIA_TYPE_AUDIO, &error);
-  print_error (error);
-  g_assert (ses->session);
-
-  g_object_get (ses->session, "sink-pad", &pad, NULL);
-
-  if (g_getenv ("AUDIOSRC"))
-    src = gst_parse_bin_from_description (g_getenv ("AUDIOSRC"), TRUE,
-        &error);
-  else
-    src = gst_parse_bin_from_description (DEFAULT_AUDIOSRC, TRUE,
-        &error);
-  print_error (error);
-  g_assert (src);
-
-  g_assert (gst_bin_add (GST_BIN (pipeline), src));
-
-  pad2 = gst_element_get_static_pad (src, "src");
-  g_assert (pad2);
-
-  g_assert (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (pad2, pad)));
-
-  gst_object_unref (pad2);
-  gst_object_unref (pad);
-
-
-  cands = g_list_prepend (NULL, fs_candidate_new ("", FS_COMPONENT_RTP,
-          FS_CANDIDATE_TYPE_HOST, FS_NETWORK_PROTOCOL_UDP, NULL, localport));
-
-  param.name = "preferred-local-candidates";
-  g_value_init (&param.value, FS_TYPE_CANDIDATE_LIST);
-  g_value_take_boxed (&param.value, cands);
-
-  ses->stream = fs_session_new_stream (ses->session, part, FS_DIRECTION_BOTH,
-      "rawudp", 1, &param, &error);
-  print_error (error);
-  g_assert (ses->stream);
-
-  g_value_unset (&param.value);
-
-  g_signal_connect (ses->stream, "src-pad-added",
-      G_CALLBACK (src_pad_added_cb), pipeline);
-
-  cands = g_list_prepend (NULL, fs_candidate_new ("", FS_COMPONENT_RTP,
-          FS_CANDIDATE_TYPE_HOST, FS_NETWORK_PROTOCOL_UDP, remoteip,
-          remoteport));
-
-  res = fs_stream_set_remote_candidates (ses->stream, cands, &error);
-  print_error (error);
-  g_assert (res);
-
-  fs_candidate_list_destroy (cands);
-
-  codecs = g_list_prepend (NULL,
-      fs_codec_new (FS_CODEC_ID_ANY, "PCMA", FS_MEDIA_TYPE_AUDIO, 0));
-  codecs = g_list_prepend (codecs,
-      fs_codec_new (FS_CODEC_ID_ANY, "PCMU", FS_MEDIA_TYPE_AUDIO, 0));
-
-  res = fs_session_set_codec_preferences (ses->session, codecs, &error);
-  print_error (error);
-  fs_codec_list_destroy (codecs);
-
-
-  g_object_get (ses->session, "codecs", &codecs, NULL);
-  res = fs_stream_set_remote_codecs (ses->stream, codecs, &error);
-  print_error (error);
-  g_assert (res);
-
-  return ses;
-}
-
-static gboolean
-async_bus_cb (GstBus *bus, GstMessage *message, gpointer user_data)
-{
-  switch (GST_MESSAGE_TYPE(message))
-  {
-    case GST_MESSAGE_ERROR:
-      {
-        GError *error = NULL;
-        gchar *debug_str = NULL;
-
-        gst_message_parse_error (message, &error, &debug_str);
-        g_error ("Got gst message: %s %s", error->message, debug_str);
-      }
-      break;
-    case GST_MESSAGE_WARNING:
-      {
-        GError *error = NULL;
-        gchar *debug_str = NULL;
-
-        gst_message_parse_warning (message, &error, &debug_str);
-        g_warning ("Got gst message: %s %s", error->message, debug_str);
-      }
-      break;
-    case GST_MESSAGE_ELEMENT:
-      {
-        const GstStructure *s = gst_message_get_structure (message);
-
-        if (gst_structure_has_name (s, "farsight-error"))
-        {
-          gint error;
-          const gchar *error_msg = gst_structure_get_string (s, "error-msg");
-          const gchar *debug_msg = gst_structure_get_string (s, "debug-msg");
-
-          g_assert (gst_structure_get_enum (s, "error-no", FS_TYPE_ERROR,
-                  &error));
-
-          if (FS_ERROR_IS_FATAL (error))
-            g_error ("Farsight fatal error: %d %s %s", error, error_msg,
-                debug_msg);
-          else
-            g_warning ("Farsight non-fatal error: %d %s %s", error, error_msg,
-                debug_msg);
-        }
-        else if (gst_structure_has_name (s, "farsight-new-local-candidate"))
-        {
-          const GValue *val = gst_structure_get_value (s, "candidate");
-          FsCandidate *cand = NULL;
-
-          g_assert (val);
-          cand = g_value_get_boxed (val);
-
-          g_print ("New candidate: %s %d\n", cand->ip, cand->port);
-        }
-        else if (gst_structure_has_name (s,
-                "farsight-local-candidates-prepared"))
-        {
-          g_print ("Local candidates prepared\n");
-        }
-        else if (gst_structure_has_name (s, "farsight-recv-codecs-changed"))
-        {
-          const GValue *val = gst_structure_get_value (s, "codecs");
-          GList *codecs = NULL;
-
-          g_assert (val);
-          codecs = g_value_get_boxed (val);
-
-          g_print ("Recv codecs changed:\n");
-          for (; codecs; codecs = g_list_next (codecs))
-          {
-            FsCodec *codec = codecs->data;
-            gchar *tmp = fs_codec_to_string (codec);
-            g_print ("%s\n", tmp);
-            g_free (tmp);
-          }
-        }
-        else if (gst_structure_has_name (s, "farsight-send-codec-changed"))
-        {
-          const GValue *val = gst_structure_get_value (s, "codec");
-          FsCodec *codec = NULL;
-          gchar *tmp;
-          g_assert (val);
-          codec = g_value_get_boxed (val);
-          tmp = fs_codec_to_string (codec);
-
-          g_print ("Send codec changed: %s\n", tmp);
-          g_free (tmp);
-        }
-      }
-      break;
-    default:
-      break;
-  }
-
-  return TRUE;
-}
-
-int main (int argc, char **argv)
-{
-  GMainLoop *loop = NULL;
-  GstElement *pipeline = NULL;
-  GstBus *bus = NULL;
-  const gchar *remoteip;
-  guint localport = 0;
-  guint remoteport = 0;
-  GstElement *conf = NULL;
-  FsParticipant *part = NULL;
-  GError *error = NULL;
-
-  gst_init (&argc, &argv);
-
-  if (argc != 4)
-  {
-    g_print ("Usage: %s <local port> <remoteip> <remoteport>\n",
-        argv[0]);
-    return 1;
-  }
-
-  localport = atoi (argv[1]);
-  remoteip = argv[2];
-  remoteport = atoi (argv[3]);
-
-  if (!localport || !remoteip || !remoteport)
-  {
-    g_print ("Usage: %s <local port> <remoteip> <remoteport>\n",
-        argv[0]);
-    return 2;
-  }
-
-  loop = g_main_loop_new (NULL, FALSE);
-
-  pipeline = gst_pipeline_new (NULL);
-
-  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
-  gst_bus_add_watch (bus, async_bus_cb, pipeline);
-  gst_object_unref (bus);
-
-  conf = gst_element_factory_make ("fsrtpconference", NULL);
-  g_assert (conf);
-
-  part = fs_conference_new_participant (FS_CONFERENCE (conf), "test at ignore",
-      &error);
-  print_error (error);
-  g_assert (part);
-
-  g_assert (gst_bin_add (GST_BIN (pipeline), conf));
-
-
-  add_audio_session (pipeline, FS_CONFERENCE (conf), 1, part, localport,
-      remoteip, remoteport);
-
-
-  g_assert (gst_element_set_state (pipeline, GST_STATE_PLAYING) !=
-      GST_STATE_CHANGE_FAILURE);
-
-  g_main_loop_run (loop);
-
-  g_assert (gst_element_set_state (pipeline, GST_STATE_NULL) !=
-      GST_STATE_CHANGE_FAILURE);
-
-  g_object_unref (part);
-
-  gst_object_unref (pipeline);
-  g_main_loop_unref (loop);
-
-  return 0;
-}
diff --git a/tests/gui/Makefile.am b/tests/gui/Makefile.am
deleted file mode 100644
index 10a8a39..0000000
--- a/tests/gui/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-EXTRA_DIST = fs2-gui.glade fs2_gui_net.py fs2-gui.py
diff --git a/tests/gui/fs2-gui.glade b/tests/gui/fs2-gui.glade
deleted file mode 100644
index b1b4151..0000000
--- a/tests/gui/fs2-gui.glade
+++ /dev/null
@@ -1,705 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--Generated with glade3 3.4.0 on Tue Jun 17 16:01:07 2008 -->
-<glade-interface>
-  <widget class="GtkWindow" id="main_window">
-    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-    <property name="border_width">6</property>
-    <property name="resizable">False</property>
-    <signal name="destroy" handler="shutdown"/>
-    <child>
-      <widget class="GtkVBox" id="vbox1">
-        <property name="visible">True</property>
-        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-        <property name="spacing">12</property>
-        <child>
-          <widget class="GtkLabel" id="info_label">
-            <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="label" translatable="yes">You are now connected to</property>
-            <property name="use_markup">True</property>
-            <property name="use_underline">True</property>
-            <property name="justify">GTK_JUSTIFY_CENTER</property>
-          </widget>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-          </packing>
-        </child>
-        <child>
-          <widget class="GtkTable" id="users_table">
-            <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="n_rows">3</property>
-            <property name="n_columns">2</property>
-            <property name="column_spacing">6</property>
-            <property name="row_spacing">6</property>
-            <child>
-              <widget class="GtkLabel" id="label4">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">Video:</property>
-              </widget>
-              <packing>
-                <property name="top_attach">2</property>
-                <property name="bottom_attach">3</property>
-                <property name="x_options">GTK_FILL</property>
-                <property name="x_padding">6</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkComboBox" id="video_combobox">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <signal name="changed" handler="video_combobox_changed_cb"/>
-              </widget>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="top_attach">2</property>
-                <property name="bottom_attach">3</property>
-                <property name="y_options">GTK_EXPAND</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkComboBox" id="audio_combobox">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <signal name="changed" handler="audio_combobox_changed_cb"/>
-              </widget>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-                <property name="y_options">GTK_EXPAND</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="label3">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">Audio:</property>
-              </widget>
-              <packing>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-                <property name="x_options">GTK_FILL</property>
-                <property name="x_padding">6</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkAspectFrame" id="preview_aspectframe">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="border_width">6</property>
-                <property name="label_xalign">0</property>
-                <property name="ratio">1.3300000429153442</property>
-                <child>
-                  <widget class="GtkDrawingArea" id="preview_drawingarea">
-                    <property name="width_request">160</property>
-                    <property name="height_request">120</property>
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <signal name="expose_event" handler="exposed"/>
-                  </widget>
-                </child>
-                <child>
-                  <widget class="GtkLabel" id="frame_label">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label" translatable="yes">&lt;b&gt;User&lt;/b&gt;</property>
-                    <property name="use_markup">True</property>
-                  </widget>
-                  <packing>
-                    <property name="type">label_item</property>
-                  </packing>
-                </child>
-              </widget>
-              <packing>
-                <property name="right_attach">2</property>
-              </packing>
-            </child>
-          </widget>
-          <packing>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child>
-          <widget class="GtkHButtonBox" id="hbuttonbox1">
-            <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="spacing">6</property>
-            <property name="layout_style">GTK_BUTTONBOX_EDGE</property>
-            <child>
-              <widget class="GtkButton" id="dtmf_button">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">DTMF</property>
-                <property name="response_id">0</property>
-                <signal name="clicked" handler="show_dtmf"/>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkButton" id="button2">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="has_focus">True</property>
-                <property name="is_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">gtk-quit</property>
-                <property name="use_stock">True</property>
-                <property name="response_id">-4</property>
-                <signal name="clicked" handler="shutdown"/>
-              </widget>
-              <packing>
-                <property name="pack_type">GTK_PACK_END</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </widget>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">2</property>
-          </packing>
-        </child>
-      </widget>
-    </child>
-  </widget>
-  <widget class="GtkWindow" id="window1">
-    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-    <child>
-      <widget class="GtkAspectFrame" id="user_frame">
-        <property name="visible">True</property>
-        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-        <property name="border_width">6</property>
-        <property name="label_xalign">0</property>
-        <property name="ratio">1.3300000429153442</property>
-        <child>
-          <widget class="GtkDrawingArea" id="user_drawingarea">
-            <property name="width_request">160</property>
-            <property name="height_request">120</property>
-            <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <signal name="expose_event" handler="exposed"/>
-          </widget>
-        </child>
-        <child>
-          <widget class="GtkLabel" id="frame_label">
-            <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="label" translatable="yes">&lt;b&gt;User&lt;/b&gt;</property>
-            <property name="use_markup">True</property>
-          </widget>
-          <packing>
-            <property name="type">label_item</property>
-          </packing>
-        </child>
-      </widget>
-    </child>
-  </widget>
-  <widget class="GtkDialog" id="neworconnect_dialog">
-    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-    <property name="border_width">5</property>
-    <property name="resizable">False</property>
-    <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
-    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
-    <property name="has_separator">False</property>
-    <signal name="close" handler="quit"/>
-    <signal name="destroy" handler="quit"/>
-    <child internal-child="vbox">
-      <widget class="GtkVBox" id="dialog-vbox2">
-        <property name="visible">True</property>
-        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-        <property name="spacing">2</property>
-        <child>
-          <widget class="GtkTable" id="table3">
-            <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="border_width">6</property>
-            <property name="n_rows">3</property>
-            <property name="n_columns">3</property>
-            <property name="column_spacing">12</property>
-            <property name="row_spacing">12</property>
-            <child>
-              <widget class="GtkLabel" id="label1">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-              </widget>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="right_attach">3</property>
-                <property name="top_attach">2</property>
-                <property name="bottom_attach">3</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkImage" id="image5">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="yalign">0</property>
-                <property name="icon_size">6</property>
-                <property name="icon_name">start-here</property>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkEntry" id="newip_entry">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="text" translatable="yes">127.0.0.1</property>
-              </widget>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">3</property>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-                <property name="y_options">GTK_FILL</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="label9">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">Port: </property>
-              </widget>
-              <packing>
-                <property name="top_attach">2</property>
-                <property name="bottom_attach">3</property>
-                <property name="y_options">GTK_FILL</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="label10">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">IP address: </property>
-              </widget>
-              <packing>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-                <property name="y_options">GTK_FILL</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="label11">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">Enter the IP address and the port of the server to connect to, or only the port if you want to start a new server</property>
-                <property name="wrap">True</property>
-              </widget>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">3</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkSpinButton" id="newport_spinbutton">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="max_length">5</property>
-                <property name="width_chars">5</property>
-                <property name="adjustment">9392 0 65535 1 10 10</property>
-                <property name="snap_to_ticks">True</property>
-                <property name="numeric">True</property>
-              </widget>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="top_attach">2</property>
-                <property name="bottom_attach">3</property>
-                <property name="x_options">GTK_SHRINK</property>
-              </packing>
-            </child>
-          </widget>
-          <packing>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child internal-child="action_area">
-          <widget class="GtkHButtonBox" id="dialog-action_area2">
-            <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="layout_style">GTK_BUTTONBOX_END</property>
-            <child>
-              <widget class="GtkButton" id="button7">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">gtk-close</property>
-                <property name="use_stock">True</property>
-                <property name="response_id">-4</property>
-                <signal name="clicked" handler="quit"/>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkButton" id="button6">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="response_id">2</property>
-                <signal name="clicked" handler="new_server"/>
-                <child>
-                  <widget class="GtkHBox" id="hbox3">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <child>
-                      <widget class="GtkImage" id="image3">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="stock">gtk-new</property>
-                      </widget>
-                      <packing>
-                        <property name="expand">False</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <widget class="GtkLabel" id="label5">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="label" translatable="yes">_New server</property>
-                        <property name="use_underline">True</property>
-                      </widget>
-                      <packing>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </widget>
-                </child>
-              </widget>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkButton" id="button5">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">gtk-connect</property>
-                <property name="use_stock">True</property>
-                <property name="response_id">1</property>
-                <signal name="clicked" handler="connect"/>
-              </widget>
-              <packing>
-                <property name="position">2</property>
-              </packing>
-            </child>
-          </widget>
-          <packing>
-            <property name="expand">False</property>
-            <property name="pack_type">GTK_PACK_END</property>
-          </packing>
-        </child>
-      </widget>
-    </child>
-  </widget>
-  <widget class="GtkWindow" id="dtmf_window">
-    <property name="visible">True</property>
-    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-    <property name="title" translatable="yes">Send DTMF</property>
-    <child>
-      <widget class="GtkVBox" id="vbox2">
-        <property name="visible">True</property>
-        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-        <property name="spacing">12</property>
-        <child>
-          <widget class="GtkVBox" id="vbox3">
-            <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <child>
-              <widget class="GtkLabel" id="label2">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">Send DTMF as:</property>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkRadioButton" id="dtmf_as_event">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">RFC-4733 DTMF Event </property>
-                <property name="response_id">0</property>
-                <property name="active">True</property>
-                <property name="draw_indicator">True</property>
-              </widget>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkRadioButton" id="dtmf_as_sound">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">Sound</property>
-                <property name="response_id">0</property>
-                <property name="draw_indicator">True</property>
-                <property name="group">dtmf_as_event</property>
-              </widget>
-              <packing>
-                <property name="position">2</property>
-              </packing>
-            </child>
-          </widget>
-          <packing>
-            <property name="padding">6</property>
-          </packing>
-        </child>
-        <child>
-          <widget class="GtkTable" id="table1">
-            <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="n_rows">4</property>
-            <property name="n_columns">3</property>
-            <property name="column_spacing">6</property>
-            <property name="row_spacing">6</property>
-            <child>
-              <widget class="GtkButton" id="dtmf_pound">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">#</property>
-                <property name="response_id">0</property>
-                <signal name="pressed" handler="dtmf_start" object="#"/>
-                <signal name="released" handler="dtmf_stop" object="#"/>
-              </widget>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="right_attach">3</property>
-                <property name="top_attach">3</property>
-                <property name="bottom_attach">4</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkButton" id="dtmf_0">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">0</property>
-                <property name="response_id">0</property>
-                <signal name="pressed" handler="dtmf_start" object="0"/>
-                <signal name="released" handler="dtmf_stop" object="0"/>
-              </widget>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="top_attach">3</property>
-                <property name="bottom_attach">4</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkButton" id="dtmf_star">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">*</property>
-                <property name="response_id">0</property>
-                <signal name="pressed" handler="dtmf_start" object="*"/>
-                <signal name="released" handler="dtmf_stop" object="*"/>
-              </widget>
-              <packing>
-                <property name="top_attach">3</property>
-                <property name="bottom_attach">4</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkButton" id="dtmf_9">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">9</property>
-                <property name="response_id">0</property>
-                <signal name="pressed" handler="dtmf_start" object="9"/>
-                <signal name="released" handler="dtmf_stop" object="9"/>
-              </widget>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="right_attach">3</property>
-                <property name="top_attach">2</property>
-                <property name="bottom_attach">3</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkButton" id="dtmf_8">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">8</property>
-                <property name="response_id">0</property>
-                <signal name="pressed" handler="dtmf_start" object="8"/>
-                <signal name="released" handler="dtmf_stop" object="8"/>
-              </widget>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="top_attach">2</property>
-                <property name="bottom_attach">3</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkButton" id="dtmf_7">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">7</property>
-                <property name="response_id">0</property>
-                <signal name="pressed" handler="dtmf_start" object="7"/>
-                <signal name="released" handler="dtmf_stop" object="7"/>
-              </widget>
-              <packing>
-                <property name="top_attach">2</property>
-                <property name="bottom_attach">3</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkButton" id="dtmf_6">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">6</property>
-                <property name="response_id">0</property>
-                <signal name="pressed" handler="dtmf_start" object="6"/>
-                <signal name="released" handler="dtmf_stop" object="6"/>
-              </widget>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="right_attach">3</property>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkButton" id="dtmf_5">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">5</property>
-                <property name="response_id">0</property>
-                <signal name="pressed" handler="dtmf_start" object="5"/>
-                <signal name="released" handler="dtmf_stop" object="5"/>
-              </widget>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkButton" id="dtmf_4">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">4</property>
-                <property name="response_id">0</property>
-                <signal name="pressed" handler="dtmf_start" object="4"/>
-                <signal name="released" handler="dtmf_stop" object="4"/>
-              </widget>
-              <packing>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkButton" id="dtmf_3">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">3</property>
-                <property name="response_id">0</property>
-                <signal name="pressed" handler="dtmf_start" object="3"/>
-                <signal name="released" handler="dtmf_stop" object="3"/>
-              </widget>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="right_attach">3</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkButton" id="dtmf_2">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">2</property>
-                <property name="response_id">0</property>
-                <signal name="pressed" handler="dtmf_start" object="2"/>
-                <signal name="released" handler="dtmf_stop" object="2"/>
-              </widget>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkButton" id="dtmf_1">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">1</property>
-                <property name="response_id">0</property>
-                <signal name="pressed" handler="dtmf_start" object="1"/>
-                <signal name="released" handler="dtmf_stop" object="1"/>
-              </widget>
-            </child>
-          </widget>
-          <packing>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child>
-          <widget class="GtkHBox" id="hbox1">
-            <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="spacing">6</property>
-            <child>
-              <widget class="GtkButton" id="button1">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">gtk-close</property>
-                <property name="use_stock">True</property>
-                <property name="response_id">0</property>
-                <signal name="clicked" handler="dtmf_destroy"/>
-              </widget>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="padding">6</property>
-                <property name="pack_type">GTK_PACK_END</property>
-              </packing>
-            </child>
-          </widget>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="padding">6</property>
-            <property name="position">2</property>
-          </packing>
-        </child>
-      </widget>
-    </child>
-  </widget>
-</glade-interface>
diff --git a/tests/gui/fs2-gui.py b/tests/gui/fs2-gui.py
deleted file mode 100755
index f744618..0000000
--- a/tests/gui/fs2-gui.py
+++ /dev/null
@@ -1,929 +0,0 @@
-#!/usr/bin/python
-
-# Farsight 2 demo GUI program
-#
-# Copyright (C) 2007 Collabora, Nokia
-# @author: Olivier Crete <olivier.crete at collabora.co.uk>
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
-#
-
-import sys, os, pwd, os.path
-import socket
-import threading
-import weakref
-
-import signal
-
-try:
-    import pygtk
-    pygtk.require("2.0")
-
-    import gtk, gtk.glade, gobject, gtk.gdk
-    import gobject
-except ImportError, e:
-    raise SystemExit("PyGTK couldn't be found ! (%s)" % (e[0]))
-
-try:
-    import pygst
-    pygst.require('0.10')
-        
-    import gst
-except ImportError, e:
-    raise SystemExit("Gst-Python couldn't be found! (%s)" % (e[0]))
-try:
-    import farsight
-except:
-    try:
-        sys.path.append(os.path.join(os.path.dirname(__file__),
-                                     '..', '..', 'python', '.libs'))
-        import farsight
-    except ImportError, e:
-        raise SystemExit("Farsight couldn't be found! (%s)" % (e[0]))
-
-
-
-from fs2_gui_net import  FsUIClient, FsUIListener, FsUIServer
-
-CAMERA=False
-
-AUDIO=True
-VIDEO=True
-
-CLIENT=1
-SERVER=2
-
-TRANSMITTER="rawudp"
-
-mycname = "".join((pwd.getpwuid(os.getuid())[0],
-                   "-" ,
-                   str(os.getpid()),
-                   "@",
-                   socket.gethostname()))
-
-gladefile = os.path.join(os.path.dirname(__file__),"fs2-gui.glade")
-
-
-def make_video_sink(pipeline, xid, name, async=True):
-    "Make a bin with a video sink in it, that will be displayed on xid."
-    bin = gst.Bin("videosink_%d" % xid)
-    sink = gst.element_factory_make("ximagesink", name)
-    sink.set_property("sync", async)
-    sink.set_property("async", async)
-    bin.add(sink)
-    colorspace = gst.element_factory_make("ffmpegcolorspace")
-    bin.add(colorspace)
-    videoscale = gst.element_factory_make("videoscale")
-    bin.add(videoscale)
-    videoscale.link(colorspace)
-    colorspace.link(sink)
-    bin.add_pad(gst.GhostPad("sink", videoscale.get_pad("sink")))
-    sink.set_data("xid", xid)
-    return bin
-
-
-class FsUIPipeline:
-    "Object to wrap the GstPipeline"
-
-    def int_handler(self, sig, frame):
-        try:
-            gst.DEBUG_BIN_TO_DOT_FILE(self.pipeline, 0, "pipelinedump")
-        except:
-            pass
-        sys.exit(2)
-    
-    def __init__(self, elementname="fsrtpconference"):
-        self.pipeline = gst.Pipeline()
-        signal.signal(signal.SIGINT, self.int_handler)
-        notifier = farsight.ElementAddedNotifier()
-        notifier.connect("element-added", self.element_added_cb)
-        notifier.add(self.pipeline)
-        self.pipeline.get_bus().set_sync_handler(self.sync_handler)
-        self.pipeline.get_bus().add_watch(self.async_handler)
-        self.conf = gst.element_factory_make(elementname)
-        # Sets lets our own cname
-        self.conf.set_property("sdes-cname", mycname)
-        self.pipeline.add(self.conf)
-        if VIDEO:
-            self.videosource = FsUIVideoSource(self.pipeline)
-            self.videosession = FsUISession(self.conf, self.videosource)
-        if AUDIO:
-            self.audiosource = FsUIAudioSource(self.pipeline)
-            self.audiosession = FsUISession(self.conf, self.audiosource)
-            self.adder = None
-        self.pipeline.set_state(gst.STATE_PLAYING)
-
-    def __del__(self):
-        self.pipeline.set_state(gst.STATE_NULL)
-
-    def sync_handler(self, bus, message):
-        "Message handler to get the prepare-xwindow-id event"
-        if message.type == gst.MESSAGE_ELEMENT and \
-               message.structure.has_name("prepare-xwindow-id"):
-            xid = None
-            element = message.src
-            # We stored the XID on the element or its parent on the expose event
-            # Now lets look it up
-            while not xid and element:
-                xid = element.get_data("xid")
-                element = element.get_parent()
-            if xid:
-                message.src.set_xwindow_id(xid)
-                return gst.BUS_DROP
-        return gst.BUS_PASS
-
-    def async_handler(self, bus, message):
-        "Async handler to print messages"
-        if message.type == gst.MESSAGE_ERROR:
-            print message.src.get_name(), ": ", message.parse_error()
-        elif message.type == gst.MESSAGE_WARNING:
-            print message.src.get_name(), ": ", message.parse_warning()
-        elif message.type == gst.MESSAGE_ELEMENT:
-            if message.structure.has_name("dtmf-event"):
-                print "dtmf-event: %d" % message.structure["number"]
-            elif message.structure.has_name("farsight-local-candidates-prepared"):
-                message.structure["stream"].uistream.local_candidates_prepared()
-
-            elif message.structure.has_name("farsight-new-local-candidate"):
-                message.structure["stream"].uistream.new_local_candidate(
-                    message.structure["candidate"])
-            elif message.structure.has_name("farsight-codecs-changed"):
-                print message.src.get_name(), ": ", message.structure.get_name()
-                message.structure["session"].uisession.codecs_changed()
-                if AUDIO and message.structure["session"] == self.audiosession.fssession:
-                    self.codecs_changed_audio()
-                if VIDEO and  message.structure["session"] == self.videosession.fssession:
-                    self.codecs_changed_video()
-            elif message.structure.has_name("farsight-send-codec-changed"):
-                print message.src.get_name(), ": ", message.structure.get_name()
-                print "send codec changed: " + message.structure["codec"].to_string()
-                if AUDIO and message.structure["session"] == self.audiosession.fssession:
-                    self.codecs_changed_audio()
-                if VIDEO and message.structure["session"] == self.videosession.fssession:
-                    self.codecs_changed_video()
-            elif message.structure.has_name("farsight-recv-codecs-changed"):
-                print message.src.get_name(), ": ", message.structure.get_name()
-                message.structure["stream"].uistream.recv_codecs_changed( \
-                    message.structure["codecs"])
-                
-                
-            elif message.structure.has_name("farsight-error"):
-                print "Async error ("+ str(message.structure["error-no"]) +"): " + message.structure["error-msg"] +" --- "+ message.structure["debug-msg"]
-            else:
-                print message.src.get_name(), ": ", message.structure.get_name()
-        elif message.type != gst.MESSAGE_STATE_CHANGED \
-                 and message.type != gst.MESSAGE_ASYNC_DONE:
-            print message.type
-        
-        return True
-
-    def make_video_preview(self, xid, newsize_callback):
-        "Creates the preview sink"
-        self.previewsink = make_video_sink(self.pipeline, xid,
-                                           "previewvideosink", False)
-        self.pipeline.add(self.previewsink)
-        #Add a probe to wait for the first buffer to find the image size
-        self.havesize = self.previewsink.get_pad("sink").add_buffer_probe(self.have_size,
-                                                          newsize_callback)
-                                                          
-        self.previewsink.set_state(gst.STATE_PLAYING)
-        self.videosource.tee.link(self.previewsink)
-        self.pipeline.set_state(gst.STATE_PLAYING)
-        return self.previewsink
-
-    def have_size(self, pad, buffer, callback):
-        "Callback on the first buffer to know the drawingarea size"
-        x = buffer.caps[0]["width"]
-        y = buffer.caps[0]["height"]
-        callback(x,y)
-        self.previewsink.get_pad("sink").remove_buffer_probe(self.havesize)
-        return True
-
-    def link_audio_sink(self, pad):
-        "Link the audio sink to the pad"
-        print >>sys.stderr, "LINKING AUDIO SINK"
-        if not self.adder:
-            audiosink = gst.element_factory_make("alsasink")
-            audiosink.set_property("buffer-time", 50000)
-            self.pipeline.add(audiosink)
-
-            try:
-                self.adder = gst.element_factory_make("liveadder")
-            except gst.ElementNotFoundError:
-                audiosink.set_state(gst.STATE_PLAYING)
-                pad.link(audiosink.get_pad("sink"))
-                return
-            self.pipeline.add(self.adder)
-            audiosink.set_state(gst.STATE_PLAYING)
-            self.adder.link(audiosink)
-            self.adder.set_state(gst.STATE_PLAYING)
-        convert1 = gst.element_factory_make("audioconvert")
-        self.pipeline.add(convert1)
-        resample = gst.element_factory_make("audioresample")
-        self.pipeline.add(resample)
-        convert2 = gst.element_factory_make("audioconvert")
-        self.pipeline.add(convert2)
-        convert1.link(resample)
-        resample.link(convert2)
-        convert2.link(self.adder)
-        pad.link(convert1.get_pad("sink"))
-        convert2.set_state(gst.STATE_PLAYING)
-        resample.set_state(gst.STATE_PLAYING)
-        convert1.set_state(gst.STATE_PLAYING)
-
-    def element_added_cb(self, notifier, bin, element):
-        if element.get_factory().get_name() == "x264enc":
-            element.set_property("byte-stream", True)
-            element.set_property("bitrate", 128)
-        elif element.get_factory().get_name() == "gstrtpbin":
-            element.set_property("latency", 100)
-            
-
-class FsUISource:
-    "An abstract generic class for media sources"
-
-    def __init__(self, pipeline):
-        self.pipeline = pipeline
-        self.tee = gst.element_factory_make("tee")
-        pipeline.add(self.tee)
-        self.tee.set_state(gst.STATE_PLAYING)
-
-        self.source = self.make_source()
-        pipeline.add(self.source)
-        self.source.link(self.tee)
-        self.playcount = 0
-
-    def __del__(self):
-        self.source.set_state(gst.STATE_NULL)
-        self.tee.set_state(gst.STATE_NULL)
-        self.pipeline.remove(self.source)
-        self.pipeline.remove(self.tee)
-        
-        
-    def make_source(self):
-        "Creates and returns the source GstElement"
-        raise NotImplementedError()
-
-
-    def get_type(self):
-        "Returns the FsMediaType of the source."
-        raise NotImplementedError()
-
-    def get_src_pad(self, name="src%d"):
-        "Gets a source pad from the source"
-        queue = gst.element_factory_make("queue")
-        queue.set_property("leaky", 2)
-        queue.set_property("max-size-time", 50*gst.MSECOND)
-        requestpad = self.tee.get_request_pad(name)
-        self.pipeline.add(queue)
-        requestpad.link(queue.get_static_pad("sink"))
-        pad = queue.get_static_pad("src")
-        pad.set_data("requestpad", requestpad)
-        pad.set_data("queue", queue)
-        return pad
-
-    def put_src_pad(self, pad):
-        "Puts the source pad from the source"
-        self.pipeline.remove(pad.get_data("queue"))
-        self.tee.release_request_pad(pad.get_data("requestpad"))
-    
-
-class FsUIVideoSource(FsUISource):
-    "A Video source"
-    
-    def get_type(self):
-        return farsight.MEDIA_TYPE_VIDEO
-
-    def make_source(self):
-        bin = gst.Bin()
-        if CAMERA:
-            source = gst.element_factory_make("v4l2src")
-            source.set_property("device", CAMERA)
-            bin.add(source)
-        else:
-            source = gst.element_factory_make("videotestsrc")
-            source.set_property("is-live", 1)
-            bin.add(source)
-            overlay = gst.element_factory_make("timeoverlay")
-            overlay.set_property("font-desc", "Sans 32")
-            bin.add(overlay)
-            source.link(overlay)
-            source=overlay
-
-        filter = gst.element_factory_make("capsfilter")
-        filter.set_property("caps", gst.Caps("video/x-raw-yuv , width=[300,500] , height=[200,500], framerate=[20/1,30/1]"))
-        bin.add(filter)
-        source.link(filter)
-
-        videoscale = gst.element_factory_make("videoscale")
-        bin.add(videoscale)
-        filter.link(videoscale)
-
-        bin.add_pad(gst.GhostPad("src", videoscale.get_pad("src")))
-        return bin
-            
-      
-
-class FsUIAudioSource(FsUISource):
-    "An audio source"
-
-    def get_type(self):
-        return farsight.MEDIA_TYPE_AUDIO
-
-    def make_source(self):
-        source = gst.element_factory_make("audiotestsrc")
-        source.set_property("is-live", True)
-        source.set_property("wave", 5)
-        return source
-        #return gst.element_factory_make("alsasrc")
-        #return gst.element_factory_make("gconfaudiosrc")
-
-
-
-class FsUISession:
-    "This is one session (audio or video depending on the source)"
-    
-    def __init__(self, conference, source):
-        self.conference = conference
-        self.source = source
-        self.streams = []
-        self.fssession = conference.new_session(source.get_type())
-        self.fssession.uisession = self
-        if source.get_type() == farsight.MEDIA_TYPE_VIDEO:
-            # We prefer H263-1998 because we know it works
-            # We don't know if the others do work
-            # We know H264 doesn't work for now or anything else
-            # that needs to send config data
-            self.fssession.set_codec_preferences( [ \
-                farsight.Codec(farsight.CODEC_ID_ANY,
-                               "THEORA",
-                               farsight.MEDIA_TYPE_VIDEO,
-                               90000),
-                farsight.Codec(farsight.CODEC_ID_ANY,
-                               "H264",
-                               farsight.MEDIA_TYPE_VIDEO,
-                               0),
-                farsight.Codec(farsight.CODEC_ID_ANY,
-                               "H263-1998",
-                               farsight.MEDIA_TYPE_VIDEO,
-                               0),
-                farsight.Codec(farsight.CODEC_ID_ANY,
-                               "H263",
-                               farsight.MEDIA_TYPE_VIDEO,
-                               0)
-                ])
-        elif source.get_type() == farsight.MEDIA_TYPE_AUDIO:
-            self.fssession.set_codec_preferences( [ \
-                farsight.Codec(farsight.CODEC_ID_ANY,
-                               "PCMA",
-                               farsight.MEDIA_TYPE_AUDIO,
-                               0),
-                farsight.Codec(farsight.CODEC_ID_ANY,
-                               "PCMU",
-                               farsight.MEDIA_TYPE_AUDIO,
-                               0),
-                # The gst speexenc element breaks timestamps
-                farsight.Codec(farsight.CODEC_ID_DISABLE,
-                               "SPEEX",
-                               farsight.MEDIA_TYPE_AUDIO,
-                               16000),
-                # Sadly, vorbis is not currently compatible with live streaming :-(
-                farsight.Codec(farsight.CODEC_ID_DISABLE,
-                               "VORBIS",
-                               farsight.MEDIA_TYPE_AUDIO,
-                               0),
-                ])
-
-        self.sourcepad = self.source.get_src_pad()
-        self.sourcepad.link(self.fssession.get_property("sink-pad"))
-
-    def __del__(self):
-        self.sourcepad(unlink)
-        self.source.put_src_pad(self.sourcepad)
-    def __stream_finalized(self, s):
-        self.streams.remove(s)
-            
-    def new_stream(self, id, participant):
-        "Creates a new stream for a specific participant"
-        transmitter_params = {}
-        # If its video, we start at port 9078, to make it more easy
-        # to differentiate it in a tcpdump log
-        if self.source.get_type() == farsight.MEDIA_TYPE_VIDEO and \
-               TRANSMITTER == "rawudp":
-            cand = farsight.Candidate()
-            cand.component_id = farsight.COMPONENT_RTP
-            cand.port = 9078
-            transmitter_params["preferred-local-candidates"] = [cand]
-        realstream = self.fssession.new_stream(participant.fsparticipant,
-                                             farsight.DIRECTION_BOTH,
-                                             TRANSMITTER, transmitter_params)
-        stream = FsUIStream(id, self, participant, realstream)
-        self.streams.append(weakref.ref(stream, self.__stream_finalized))
-        return stream
-
-    def dtmf_start(self, event, method):
-        if (event == "*"):
-            event = farsight.DTMF_EVENT_STAR
-        elif (event == "#"):
-            event = farsight.DTMF_EVENT_POUND
-        else:
-            event = int(event)
-        self.fssession.start_telephony_event(event, 2, method)
-        
-    def dtmf_stop(self, method):
-        self.fssession.stop_telephony_event(method)
-
-    def codecs_changed(self):
-        "Callback from FsSession"
-        for s in self.streams:
-            try:
-                s().codecs_changed()
-            except AttributeError:
-                pass
-
-    def send_stream_codecs(self, codecs, sourcestream):
-        for s in self.streams:
-            stream = s()
-            if stream and stream is not sourcestream:
-                stream.connect.send_codecs(stream.participant.id,
-                                           sourcestream.id,
-                                           codecs,
-                                           sourcestream.participant.id)
-
-class FsUIStream:
-    "One participant in one session"
-
-    def __init__(self, id, session, participant, fsstream):
-        self.id = id
-        self.session = session
-        self.participant = participant
-        self.fsstream = fsstream
-        self.connect = participant.connect
-        self.fsstream.uistream = self
-        self.fsstream.connect("src-pad-added", self.__src_pad_added)
-        self.send_codecs = False
-        self.last_codecs = None
-        self.last_stream_codecs = None
-        self.candidates = []
-
-    def local_candidates_prepared(self):
-        "Callback from FsStream"
-        self.connect.send_candidates_done(self.participant.id, self.id)
-    def new_local_candidate(self, candidate):
-        "Callback from FsStream"
-        self.connect.send_candidate(self.participant.id, self.id, candidate)
-    def __src_pad_added(self, stream, pad, codec):
-        "Callback from FsStream"
-        if self.session.source.get_type() == farsight.MEDIA_TYPE_VIDEO:
-            self.participant.link_video_sink(pad)
-        else:
-            self.participant.pipeline.link_audio_sink(pad)
-
-    def candidate(self, candidate):
-        "Callback for the network object."
-        self.candidates.append(candidate)
-    def candidates_done(self):
-        "Callback for the network object."
-        self.fsstream.set_remote_candidates(self.candidates)
-        self.candidates = []
-    def codecs(self, codecs):
-        "Callback for the network object. Set the codecs"
-
-        print "Remote codecs"
-        for c in codecs:
-            print "Got remote codec from %s/%s %s" % \
-                  (self.participant.id, self.id, c.to_string())
-        oldcodecs = self.fsstream.get_property("remote-codecs")
-        if oldcodecs == codecs:
-            return
-        try:
-            self.fsstream.set_remote_codecs(codecs)
-        except AttributeError:
-            print "Tried to set codecs with 0 codec"
-        self.send_local_codecs()
-        self.send_stream_codecs()
-
-
-    def send_local_codecs(self):
-        "Callback for the network object."
-        self.send_codecs = True
-        self.check_send_local_codecs()
-
-    def codecs_changed(self):
-        self.check_send_local_codecs()
-        self.send_stream_codecs()
-
-    def check_send_local_codecs(self):
-        "Internal function to send our local codecs when they're ready"
-        if not self.send_codecs:
-            return
-        if not self.session.fssession.get_property("codecs-ready"):
-            print "Codecs are not ready"
-            return
-        codecs = self.session.fssession.get_property("codecs")
-        assert(codecs is not None and len(codecs) > 0)
-        if (codecs == self.last_codecs):
-            return
-        self.last_codecs = codecs
-        print "sending local codecs"
-        self.connect.send_codecs(self.participant.id, self.id, codecs)
-
-    def send_stream_codecs(self):
-        if not self.connect.is_server:
-            return
-        if not self.session.fssession.get_property("codecs-ready"):
-            return
-        codecs = self.fsstream.get_property("negotiated-codecs")
-        if codecs:
-            self.session.send_stream_codecs(codecs, self)
-
-    def recv_codecs_changed(self, codecs):
-        self.participant.recv_codecs_changed()
-
-
-    def __remove_from_send_codecs_to(self, participant):
-        self.send_codecs_to.remote(participant)
-
-
-    def send_codecs_to(self, participant):
-        codecs = self.fsstream.get_property("negotiated-codecs")
-        print "sending stream %s codecs from %s to %s" % \
-              (self.id, self.participant.id, participant.id)
-        if codecs:
-            participant.connect.send_codecs(participant.id, self.id, codecs,
-                                            self.participant.id)            
-
-
-class FsUIParticipant:
-    "Wraps one FsParticipant, is one user remote contact"
-    
-    def __init__(self, connect, id, cname, pipeline, mainui):
-        self.connect = connect
-        self.id = id
-        self.cname = cname
-        self.pipeline = pipeline
-        self.mainui = mainui
-        self.fsparticipant = pipeline.conf.new_participant(cname)
-        self.outcv = threading.Condition()
-        self.funnel = None
-        self.make_widget()
-        self.streams = {}
-        if VIDEO:
-            self.streams[int(farsight.MEDIA_TYPE_VIDEO)] = \
-              pipeline.videosession.new_stream(
-                int(farsight.MEDIA_TYPE_VIDEO), self)
-        if AUDIO:
-            self.streams[int(farsight.MEDIA_TYPE_AUDIO)] = \
-              pipeline.audiosession.new_stream(
-                int(farsight.MEDIA_TYPE_AUDIO), self)
-        
-    def candidate(self, media, candidate):
-        "Callback for the network object."
-        self.streams[media].candidate(candidate)
-    def candidates_done(self, media):
-        "Callback for the network object."
-        self.streams[media].candidates_done()
-    def codecs(self, media, codecs):
-        "Callback for the network object."
-        self.streams[media].codecs(codecs)
-    def send_local_codecs(self):
-        "Callback for the network object."
-        for id in self.streams:
-            self.streams[id].send_local_codecs()
-
-    def make_widget(self):
-        "Make the widget of the participant's video stream."
-        gtk.gdk.threads_enter()
-        self.glade = gtk.glade.XML(gladefile, "user_frame")
-        self.userframe = self.glade.get_widget("user_frame")
-        self.glade.get_widget("frame_label").set_text(self.cname)
-        self.glade.signal_autoconnect(self)
-        self.label = gtk.Label()
-        self.label.set_alignment(0,0)
-        self.label.show()
-        self.mainui.hbox_add(self.userframe, self.label)
-        gtk.gdk.threads_leave()
-
-    def exposed(self, widget, *args):
-        """From the exposed signal, used to create the video sink
-        The video sink will be created here, but will only be linked when the
-        pad arrives and link_video_sink() is called.
-        """
-        if not VIDEO:
-            return
-        try:
-            self.videosink.get_by_interface(gst.interfaces.XOverlay).expose()
-        except AttributeError:
-            try:
-                self.outcv.acquire()
-                self.videosink = make_video_sink(self.pipeline.pipeline,
-                                                 widget.window.xid,
-                                                 "uservideosink")
-                self.pipeline.pipeline.add(self.videosink)
-                self.funnel = gst.element_factory_make("fsfunnel")
-                self.pipeline.pipeline.add(self.funnel)
-                self.funnel.link(self.videosink)
-                self.havesize = self.videosink.get_pad("sink").add_buffer_probe(self.have_size)
-
-                self.videosink.set_state(gst.STATE_PLAYING)
-                self.funnel.set_state(gst.STATE_PLAYING)
-                self.outcv.notifyAll()
-            finally:
-                self.outcv.release()
-            
-
-    def have_size(self, pad, buffer):
-        "Callback on the first buffer to know the drawingarea size"
-        x = buffer.caps[0]["width"]
-        y = buffer.caps[0]["height"]
-        gtk.gdk.threads_enter()
-        self.glade.get_widget("user_drawingarea").set_size_request(x,y)
-        gtk.gdk.threads_leave()
-        self.videosink.get_pad("sink").remove_buffer_probe(self.havesize)
-        del self.havesize
-        return True
-                 
-
-
-    def link_video_sink(self, pad):
-        """Link the video sink
-
-        Wait for the funnnel for the video sink to be created, when it has been
-        created, link it.
-        """
-        try:
-            self.outcv.acquire()
-            while self.funnel is None:
-                self.outcv.wait()
-            print >>sys.stderr, "LINKING VIDEO SINK"
-            pad.link(self.funnel.get_pad("sink%d"))
-        finally:
-            self.outcv.release()
-
-    def destroy(self):
-        if VIDEO:
-            try:
-                self.videosink.get_pad("sink").disconnect_handler(self.havesize)
-                pass
-            except AttributeError:
-                pass
-            self.glade.get_widget("user_drawingarea").disconnect_by_func(self.exposed)
-            self.streams = {}
-            self.outcv.acquire()
-            self.videosink.set_locked_state(True)
-            self.funnel.set_locked_state(True)
-            self.videosink.set_state(gst.STATE_NULL)
-            self.funnel.set_state(gst.STATE_NULL)
-            self.pipeline.pipeline.remove(self.videosink)
-            self.pipeline.pipeline.remove(self.funnel)
-            del self.videosink
-            del self.funnel
-            self.outcv.release()
-        gtk.gdk.threads_enter()
-        self.userframe.destroy()
-        self.label.destroy()
-        gtk.gdk.threads_leave()
-
-    def error(self):
-        "Callback for the network object."
-        if self.id == 1:
-            self.mainui.fatal_error("<b>Disconnected from server</b>")
-        else:
-            print "ERROR ON %d" % (self.id)
-
-    def recv_codecs_changed(self):
-        codecs = {}
-        for s in self.streams:
-            codec = self.streams[s].fsstream.get_property("current-recv-codecs")
-            mediatype = self.streams[s].session.fssession.get_property("media-type")
-            if len(codec):
-                if mediatype in codecs:
-                    codecs[mediatype] += codec
-                else:
-                    codecs[mediatype] = codec
-        str = ""
-        for mt in codecs:
-            str += "<big>" +mt.value_nick.title() + "</big>:\n"
-            for c in codecs[mt]:
-                str += "  <b>%s</b>: %s %s\n" % (c.id, 
-                                                 c.encoding_name,
-                                                 c.clock_rate)
-        self.label.set_markup(str)
-
-    def send_codecs_to(self, participant):
-        for sid in self.streams:
-            self.streams[sid].send_codecs_to(participant)
-    
-
-class FsMainUI:
-    "The main UI and its different callbacks"
-    
-    def __init__(self, mode, ip, port):
-        self.mode = mode
-        self.pipeline = FsUIPipeline()
-        self.pipeline.codecs_changed_audio = self.reset_audio_codecs
-        self.pipeline.codecs_changed_video = self.reset_video_codecs
-        self.glade = gtk.glade.XML(gladefile, "main_window")
-        self.glade.signal_autoconnect(self)
-        self.mainwindow = self.glade.get_widget("main_window")
-        self.audio_combobox = self.glade.get_widget("audio_combobox")
-        self.video_combobox = self.glade.get_widget("video_combobox")
-        liststore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
-        self.audio_combobox.set_model(liststore)
-        cell = gtk.CellRendererText()
-        self.audio_combobox.pack_start(cell, True)
-        self.audio_combobox.add_attribute(cell, 'text', 0)
-        self.reset_audio_codecs()
-        liststore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
-        self.video_combobox.set_model(liststore)
-        cell = gtk.CellRendererText()
-        self.video_combobox.pack_start(cell, True)
-        self.video_combobox.add_attribute(cell, 'text', 0)
-        self.reset_video_codecs()
-
-        if mode == CLIENT:
-            self.client = FsUIClient(ip, port, mycname, FsUIParticipant,
-                                     self.pipeline, self)
-            self.glade.get_widget("info_label").set_markup(
-                "<b>%s</b>\nConnected to %s:%s" % (mycname, ip, port))
-        elif mode == SERVER:
-            self.server = FsUIListener(port, FsUIServer, mycname,
-                                       FsUIParticipant, self.pipeline, self)
-            self.glade.get_widget("info_label").set_markup(
-                "<b>%s</b>\nExpecting connections on port %s" %
-                (mycname, self.server.port))
-
-        
-        self.mainwindow.show()
-
-    def reset_codecs(self, combobox, fssession):
-        liststore = combobox.get_model()
-        current = fssession.get_property("current-send-codec")
-        liststore.clear()
-        for c in fssession.get_property("codecs"):
-            str = ("%s: %s/%s %s" % (c.id, 
-                                     c.media_type.value_nick,
-                                     c.encoding_name,
-                                     c.clock_rate))
-            iter = liststore.append([str, c])
-            if current and c and current.id == c.id:
-                combobox.set_active_iter(iter)
-                print "active: "+ c.to_string()
-
-    def reset_audio_codecs(self):
-        if AUDIO:
-            self.reset_codecs(self.audio_combobox,
-                              self.pipeline.audiosession.fssession)
-
-    def reset_video_codecs(self):
-        if VIDEO:
-            self.reset_codecs(self.video_combobox,
-                              self.pipeline.videosession.fssession)
-
-    def combobox_changed_cb(self, combobox, fssession):
-        liststore = combobox.get_model()
-        iter = combobox.get_active_iter()
-        if iter:
-            codec = liststore.get_value(iter, 1)
-            fssession.set_send_codec(codec)
-
-    def audio_combobox_changed_cb(self, combobox):
-        self.combobox_changed_cb(combobox, self.pipeline.audiosession.fssession)
-    
-    def video_combobox_changed_cb(self, combobox):
-        self.combobox_changed_cb(combobox, self.pipeline.videosession.fssession)
-        
-        
-    def exposed(self, widget, *args):
-        "Callback from the exposed event of the widget to make the preview sink"
-        if not VIDEO:
-            return
-        try:
-            self.preview.get_by_interface(gst.interfaces.XOverlay).expose()
-        except AttributeError:
-            self.preview = self.pipeline.make_video_preview(widget.window.xid,
-                                                            self.newsize)
-
-    def newsize (self, x, y):
-        self.glade.get_widget("preview_drawingarea").set_size_request(x,y)
-        
-    def shutdown(self, widget=None):
-        gtk.main_quit()
-        
-    def hbox_add(self, widget, label):
-        table = self.glade.get_widget("users_table")
-        x = table.get_properties("n-columns")[0]
-        table.attach(widget, x, x+1, 0, 1)
-        table.attach(label, x, x+1, 1, 3, xpadding=6)
-
-    def __del__(self):
-        self.mainwindow.destroy()
-
-    def fatal_error(self, errormsg):
-        gtk.gdk.threads_enter()
-        dialog = gtk.MessageDialog(self.mainwindow,
-                                   gtk.DIALOG_MODAL,
-                                   gtk.MESSAGE_ERROR,
-                                   gtk.BUTTONS_OK)
-        dialog.set_markup(errormsg);
-        dialog.run()
-        dialog.destroy()
-        gtk.main_quit()
-        gtk.gdk.threads_leave()
-
-    def show_dtmf(self, button):
-        try:
-            self.dtmf.present()
-        except AttributeError:
-            self.dtmf =  gtk.glade.XML(gladefile, "dtmf_window")
-            self.dtmf.signal_autoconnect(self)
-
-    def dtmf_start(self, button):
-        if (self.dtmf.get_widget("dtmf_as_event").get_active()):
-            self.dtmf_last_method = farsight.DTMF_METHOD_RTP_RFC4733
-        elif (self.dtmf.get_widget("dtmf_as_sound").get_active()):
-            self.dtmf_last_method = farsight.DTMF_METHOD_IN_BAND
-        else:
-            print "Invalid DTMF Method"
-            return
-        self.pipeline.audiosession.dtmf_start(button.get_label(), \
-                                              self.dtmf_last_method)
-                                              
-    def dtmf_stop(self, button):
-        try:
-            self.pipeline.audiosession.dtmf_stop(self.dtmf_last_method)
-            del self.dtmf_last_method
-        except AttributeError:
-            pass
-    def dtmf_destroy(self, button):
-        self.dtmf.get_widget("dtmf_window").destroy()
-        del self.dtmf
-
-
-
-class FsUIStartup:
-    "Displays the startup window and then creates the FsMainUI"
-    
-    def __init__(self):
-        self.glade = gtk.glade.XML(gladefile, "neworconnect_dialog")
-        self.dialog = self.glade.get_widget("neworconnect_dialog")
-        self.glade.get_widget("newport_spinbutton").set_value(9893)
-        self.glade.signal_autoconnect(self)
-        self.dialog.show()
-        self.acted = False
-
-    def action(self, mode):
-        port = self.glade.get_widget("newport_spinbutton").get_value_as_int()
-        ip = self.glade.get_widget("newip_entry").get_text()
-        try:
-            self.ui = FsMainUI(mode, ip, port)
-            self.acted = True
-            self.dialog.destroy()
-            del self.glade
-            del self.dialog
-        except socket.error, e:
-            dialog = gtk.MessageDialog(self.dialog,
-                                       gtk.DIALOG_MODAL,
-                                       gtk.MESSAGE_ERROR,
-                                       gtk.BUTTONS_OK)
-            dialog.set_markup("<b>Could not connect to %s %d</b>" % (ip,port))
-            dialog.format_secondary_markup(e[1])
-            dialog.run()
-            dialog.destroy()
-        
-    def new_server(self, widget):
-        self.action(SERVER)
-
-    def connect(self, widget):
-        self.action(CLIENT)
-        
-
-    def quit(self, widget):
-        if not self.acted:
-            gtk.main_quit()
-
-
-
-
-if __name__ == "__main__":
-    if len(sys.argv) >= 2:
-        CAMERA = sys.argv[1]
-    else:
-        CAMERA = None
-    
-    gobject.threads_init()
-    gtk.gdk.threads_init()
-    startup = FsUIStartup()
-    gtk.main()
diff --git a/tests/gui/fs2_gui_net.py b/tests/gui/fs2_gui_net.py
deleted file mode 100644
index c834d77..0000000
--- a/tests/gui/fs2_gui_net.py
+++ /dev/null
@@ -1,456 +0,0 @@
-#!/usr/bin/python
-
-# Farsight 2 simple network signalling library for the demo GUI
-#
-# Copyright (C) 2007 Collabora, Nokia
-# @author: Olivier Crete <olivier.crete at collabora.co.uk>
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
-#
-
-#
-# This is the signalling code used by fs2-gui.py
-#
-
-import sys, os, pwd, os.path
-import socket, struct
-import gc
-
-
-try:
-    import pygst
-    pygst.require('0.10')
-        
-    import gst
-except ImportError, e:
-    raise SystemExit("Gst-Python couldn't be found! (%s)" % (e[0]))
-
-try:
-    import farsight
-except:
-    sys.path.append(os.path.join(os.path.dirname(__file__),
-                                 '..', '..', 'python', '.libs'))
-    import farsight
-
-import gobject
-
-class FsUIConnect:
-    ERROR = 0
-    CODECS = 1
-    CANDIDATE = 2
-    CANDIDATES_DONE = 3
-    INTRO = 4
-
-    def __reset(self):
-        self.type = None
-        self.media = None
-        self.size = struct.calcsize("!IIIIII")
-        self.data = ""
-        self.dest = -1
-        self.src = -1
- 
-    
-    def __init__(self, sock, callbacks, myid=0):
-        self.sock = sock
-        self.__reset()
-        self.callbacks = callbacks
-        self.myid = myid
-        self.partid = 1
-        self.is_server = True
-        sock.setblocking(0)
-        gobject.io_add_watch(self.sock.fileno(), gobject.IO_IN,
-                             self.__data_in)
-        gobject.io_add_watch(self.sock.fileno(),
-                             gobject.IO_ERR | gobject.IO_HUP,
-                             self.__error)
-
-    def __error(self, source, condition):
-        print "have error"
-        if (self.src >= 0):
-            self.callbacks[self.ERROR](self.src)
-        else:
-            self.callbacks[self.ERROR](self.partid)
-        return False
-
-    def __data_in(self, source, condition):
-        data = self.sock.recv(self.size-len(self.data))
-
-        if len(data) == 0:
-            print "received nothing"
-            if (self.src >= 0):
-                self.callbacks[self.ERROR](self.src)
-            else:
-                self.callbacks[self.ERROR](self.partid)
-            return False
-        
-        self.data += data
-        if len(self.data) == self.size:
-            if self.type is not None:
-                if self.type == self.CODECS:
-                    data = self.__codecs_from_string(data)
-                elif self.type == self.CANDIDATE:
-                    data = self.__candidate_from_string(data)
-                else:
-                    data = self.data
-                self.callbacks[self.type](self.src, self.dest,
-                                          self.media, data)
-                self.__reset()
-            else:
-                (check,
-                 self.src,
-                 self.dest,
-                 self.type,
-                 self.media,
-                 self.size) = struct.unpack("!IIIIII", self.data)
-                if check != 0xDEADBEEF:
-                    print "CORRUPTION"
-                    sys.exit(1)
-                if self.myid > 1 and self.dest != self.myid:
-                    print "GOT MESSAGE FOR %d, but I am %d" % (self.dest,
-                                                               self.myid)
-                    sys.exit(1)
-                self.data=""
-                if self.size == 0:
-                    self.callbacks[self.type](self.src, self.dest,
-                                              self.media, None)
-                    self.__reset()
-        return True
-
-    def __send_data(self, dest, type, media=0, data="", src=None):
-        if src is None: src = self.myid
-        if src == 0 and type != self.INTRO: raise Exception
-        try:
-            self.sock.sendall(struct.pack("!IIIIII",
-                                          0xDEADBEEF,
-                                          int(src),
-                                          int(dest),
-                                          int(type),
-                                          int(media),
-                                          len(data)))
-            self.sock.sendall(data)
-        except socket.error:
-            print "have error"
-            self.callbacks[self.ERROR](self.partid)
-
-
-    def send_error(self, dest, src):
-        self.__send_data(dest, self.ERROR, src=src)
-    def send_intro(self, dest, cname, src=None):
-        self.__send_data(dest, self.INTRO, data=cname, src=src)
-    def send_codecs(self, dest, media, codecs, src=None):
-        self.__send_data(dest, self.CODECS,
-                         media=media,
-                         data=self.__codecs_to_string(codecs), src=src)
-    def send_candidate(self, dest, media, candidate, src=None):
-        self.__send_data(dest, self.CANDIDATE, media=media,
-                         data=self.__candidate_to_string(candidate), src=src)
-    def send_candidates_done(self, dest, media, src=None):
-        self.__send_data(dest, self.CANDIDATES_DONE, media=media, src=src)
-
-    def __del__(self):
-        try:
-            self.sock.close()
-        except AttributeError:
-            pass
-
-
-    def __candidate_to_string(self, candidate):
-        return "|".join((
-            candidate.foundation,
-            str(candidate.component_id),
-            candidate.ip,
-            str(candidate.port),
-            candidate.base_ip,
-            str(candidate.base_port),
-            str(int(candidate.proto)),
-            str(candidate.priority),
-            str(int(candidate.type)),
-            candidate.username,
-            candidate.password))
-
-    def __candidate_from_string(self, string):
-        candidate = farsight.Candidate()
-        (candidate.foundation,
-         component_id,
-         candidate.ip,
-         port,
-         candidate.base_ip,
-         base_port,
-         proto,
-         priority,
-         type,
-         candidate.username,
-         candidate.password) = string.split("|")
-        candidate.component_id = int(component_id)
-        candidate.port = int(port)
-        candidate.base_port = int(base_port)
-        candidate.proto = int(proto)
-        candidate.priority = int(priority)
-        candidate.type = int(type)
-        return candidate
-
-    def __codecs_to_string(self, codecs):
-        codec_strings = []
-        for codec in codecs:
-            start = " ".join((str(codec.id),
-                              codec.encoding_name,
-                              str(int(codec.media_type)),
-                              str(codec.clock_rate),
-                              str(codec.channels)))
-            codec = "".join((start,
-                             "|",
-                             ";".join(["=".join(i) for i in codec.optional_params])))
-            codec_strings.append(codec)
-            
-        return "\n".join(codec_strings)
-
-
-    def __codecs_from_string(self, string):
-        codecs = []
-        for substring in string.split("\n"):
-            (start,end) = substring.split("|")
-            (id, encoding_name, media_type, clock_rate, channels) = start.split(" ")
-            codec = farsight.Codec(int(id), encoding_name, int(media_type),
-                               int(clock_rate))
-            codec.channels = int(channels)
-            if len(end):
-                codec.optional_params = \
-                  [tuple(x.split("=",1)) for x in end.split(";") if len(x) > 0]
-            codecs.append(codec)
-        return codecs
-
-class FsUIConnectClient (FsUIConnect):
-    def __init__(self, ip, port, callbacks):
-        sock = socket.socket()
-        sock.connect((ip, port))
-        FsUIConnect.__init__(self, sock, callbacks)
-        self.is_server = False
-
-class FsUIListener:
-    def __init__(self, port, callback, *args):
-        self.sock = socket.socket()
-        self.callback = callback
-        self.args = args
-        bound = False
-        while not bound:
-            try:
-                self.sock.bind(("", port))
-                bound = True
-            except socket.error, e:
-                port += 1
-        self.port = port
-        print "Bound to port ", port
-        self.sock.setblocking(0)
-        gobject.io_add_watch(self.sock.fileno(), gobject.IO_IN, self.data_in)
-        gobject.io_add_watch(self.sock.fileno(),
-                             gobject.IO_ERR | gobject.IO_HUP,
-                             self.error)
-        self.sock.listen(3)
-
-    def error(self, source, condition):
-        print "Error on listen"
-        sys.exit(1)
-        return False
-
-    def data_in(self, source, condition):
-        (sock,addr) = self.sock.accept()
-        self.callback(sock, *self.args)
-        return True
-    
-class FsUIClient:
-    def __init__(self, ip, port, cname, get_participant, *args):
-        self.participants = {}
-        self.get_participant = get_participant
-        self.args = args
-        self.cname = cname
-        self.connect = FsUIConnectClient(ip, port, (self.__error,
-                                                    self.__codecs,
-                                                    self.__candidate,
-                                                    self.__candidate_done,
-                                                    self.__intro))
-        self.connect.send_intro(1, cname)
-
-    def __codecs(self, src, dest, media, data):
-        print "Got codec Src:%d dest:%d data:%s" % (src, dest, data)
-        self.participants[src].codecs(media, data)
-    def __candidate(self, src, dest, media, data):
-        self.participants[src].candidate(media, data)
-    def __candidate_done(self, src, dest, media, data):
-        self.participants[src].candidates_done(media)
-    def __intro(self, src, dest, media, cname):
-        print "Got Intro from %s, I am %d" % (src, dest)
-        if src == 1:
-            self.connect.myid = dest
-        if not self.participants.has_key(src):
-            if src != 1:
-                self.connect.send_intro(src, self.cname)
-            self.participants[src] = self.get_participant(self.connect, src,
-                                                          cname,
-                                                          *self.args)
-    def __error(self, participantid, *arg):
-        print "Client Error", participantid
-        if participantid == 1:
-            # Communication error with server, its over
-            self.participants[participantid].error()
-        else:
-            self.participants[participantid].destroy()
-            del self.participants[participantid]
-            gc.collect()
-
-
-class FsUIServer:
-    nextid = 2
-    participants = {}
-
-    def __init__(self, sock, cname, get_participant, *args):
-        self.cname = cname
-        self.get_participant = get_participant
-        self.args = args
-        self.connect = FsUIConnect(sock, (self.__error,
-                                          self.__codecs,
-                                          self.__candidate,
-                                          self.__candidate_done,
-                                          self.__intro), 1)
-    def __codecs(self, src, dest, media, data):
-        FsUIServer.participants[src].codecs(media, data)
-    def __candidate(self, src, dest, media, data):
-        if dest == 1:
-            FsUIServer.participants[src].candidate(media, data)
-        else:
-            print data
-            FsUIServer.participants[dest].connect.send_candidate(dest,
-                                                                 media,
-                                                                 data,
-                                                                 src)
-    def __candidate_done(self, src, dest, media, data):
-        if dest == 1:
-            FsUIServer.participants[src].candidates_done(media)
-        else:
-            FsUIServer.participants[dest].connect.send_candidates_done(dest,
-                                                                       media,
-                                                                       src)
-    def __intro(self, src, dest, media, cname):
-        print "Got Intro from %s to %s" % (src, dest)
-        if src == 0 and dest == 1:
-            newid = FsUIServer.nextid
-            # Forward the introduction to all other participants
-            for pid in FsUIServer.participants:
-                print "Sending from %d to %d" % (newid, pid)
-                FsUIServer.participants[pid].connect.send_intro(pid, cname,
-                                                                newid)
-            self.connect.send_intro(newid, self.cname)
-            self.connect.partid = newid
-            FsUIServer.participants[newid] = self.get_participant(self.connect,
-                                                                  newid,
-                                                                  cname,
-                                                                  *self.args)
-            FsUIServer.participants[newid].send_local_codecs()
-            FsUIServer.nextid += 1
-        elif dest != 1:
-            FsUIServer.participants[dest].connect.send_intro(dest,
-                                                             cname,
-                                                             src)
-            FsUIServer.participants[src].send_codecs_to(
-                        FsUIServer.participants[dest])
-        else:
-            print "ERROR SRC != 0"
-            
-    def __error(self, participantid, *args):
-        print "Server Error", participantid
-        FsUIServer.participants[participantid].destroy()
-        del FsUIServer.participants[participantid]
-        gc.collect()
-        for pid in FsUIServer.participants:
-            FsUIServer.participants[pid].connect.send_error(pid, participantid)
-
-if __name__ == "__main__":
-    class TestMedia:
-        def __init__(self, pid, id, connect):
-            self.pid = pid
-            self.id = id
-            self.connect = connect
-            candidate = farsight.Candidate()
-            candidate.component_id = 1
-            connect.send_candidate(self.pid, self.id, candidate)
-            connect.send_candidates_done(self.pid, self.id)
-        def candidate(self, candidate):
-            print "Got candidate", candidate
-        def candidates_done(self):
-            print "Got candidate done"
-        def codecs(self, codecs):
-            if self.connect.myid != 1:
-                self.connect.send_codecs(1, self.id,
-                                        [farsight.Codec(self.connect.myid,
-                                                       "codec-name",
-                                                       self.pid,
-                                                       self.id)])
-       
-        def send_local_codecs(self):
-            print "Send local codecs to %s for media %s" % (self.pid, self.id)
-            self.connect.send_codecs(self.pid, self.id,
-                                     [farsight.Codec(self.connect.myid,
-                                                     "local_codec",
-                                                     self.pid,
-                                                     self.id)])
-        def get_codecs(self):
-            return [farsight.Codec(self.connect.myid,
-                                   "nego-codecs",
-                                   self.pid,
-                                   self.id)]
-            
-            
-    class TestParticipant:
-        def __init__(self, connect, id, cname, *args):
-            self.id = id
-            self.streams = {1: TestMedia(id, 1, connect),
-                            2: TestMedia(id, 2, connect)}
-            self.cname = cname
-            self.connect = connect
-            print "New Participant %s and cname %s" % (id,cname)
-        def candidate(self, media, candidate):
-            self.streams[media].candidate(candidate)
-        def candidates_done(self, media):
-            self.streams[media].candidates_done()
-        def codecs(self, media, codecs):
-            self.streams[media].codecs(codecs)
-        def send_local_codecs(self):
-            for id in self.streams:
-                self.streams[id].send_local_codecs()
-        def destroy(self):
-            pass
-        def send_codecs_to(self, participant):
-            for sid in self.streams:
-                print "to: %s from: %s" % (str(participant.id), (self.id))
-                participant.connect.send_codecs(participant.id,
-                                                self.streams[sid].id,
-                                                self.streams[sid].get_codecs(),
-                                                self.id)
-        def error(self):
-            print "ERROR"
-            sys.exit(1)
-        def destroy(self):
-            passs
-            
-
-    mycname = "test"
-    mainloop = gobject.MainLoop()
-    gobject.threads_init()
-    if len(sys.argv) > 1:
-        client = FsUIClient("127.0.0.1", int(sys.argv[1]),
-                            "cname" + sys.argv[1],
-                            TestParticipant)
-    else:
-        listener = FsUIListener(9893, FsUIServer, "cnameServ", TestParticipant)
-    mainloop.run()
-- 
1.5.6.5



More information about the farsight-commits mailing list