gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r33407 - gnunet-gtk/src/conversation


From: gnunet
Subject: [GNUnet-SVN] r33407 - gnunet-gtk/src/conversation
Date: Tue, 27 May 2014 00:10:01 +0200

Author: grothoff
Date: 2014-05-27 00:10:01 +0200 (Tue, 27 May 2014)
New Revision: 33407

Modified:
   gnunet-gtk/src/conversation/gnunet-conversation-gtk_contacts.c
   gnunet-gtk/src/conversation/gnunet-conversation-gtk_phone.c
Log:
major hacking on phone module

Modified: gnunet-gtk/src/conversation/gnunet-conversation-gtk_contacts.c
===================================================================
--- gnunet-gtk/src/conversation/gnunet-conversation-gtk_contacts.c      
2014-05-26 19:47:13 UTC (rev 33406)
+++ gnunet-gtk/src/conversation/gnunet-conversation-gtk_contacts.c      
2014-05-26 22:10:01 UTC (rev 33407)
@@ -29,6 +29,7 @@
 #include "gnunet-conversation-gtk.h"
 #include "gnunet-conversation-gtk_contacts.h"
 #include "gnunet-conversation-gtk_egos.h"
+#include "gnunet-conversation-gtk_phone.h"
 
 
 /**

Modified: gnunet-gtk/src/conversation/gnunet-conversation-gtk_phone.c
===================================================================
--- gnunet-gtk/src/conversation/gnunet-conversation-gtk_phone.c 2014-05-26 
19:47:13 UTC (rev 33406)
+++ gnunet-gtk/src/conversation/gnunet-conversation-gtk_phone.c 2014-05-26 
22:10:01 UTC (rev 33407)
@@ -33,42 +33,67 @@
 
 
 /**
- * active calls treeview columns
+ * Active calls treeview columns
  */
 enum ActiveCallsTreeViewColumns
 {
-  AL_caller_id, //*gchar
-  AL_caller,  //*
-  AL_caller_num, //gint
-  AL_type, //gint
-  AL_caller_state, //gint
-  AL_call, //*
-  AL_call_state, //gint
-  AL_call_num //gint
-};
+  /**
+   * A `gchar *`
+   */
+  GCG_PHONE_LS_CALLER_ID,
 
+  /**
+   * A `struct IncomingCall *`
+   */
+  GCG_PHONE_LS_CALLER,
 
-/**
- * callerstate (state of incoming call)
- */
-enum CallerState
-{
-  CT_active,
-  CT_suspended,
-  CT_ringing,
-  CT_dead,
-  CT_hangup,
-  CT_rejected,
-  CT_other
+  /**
+   * A `gint`.
+   */
+  GCG_PHONE_LS_CALLER_NUM,
+
+  /**
+   * A `gint` for a `enum TypeOfConversation` (FIXME: remove?)
+   */
+  GCG_PHONE_LS_TYPE,
+
+  /**
+   * A `gint` for a `enum InCallState` (FIXME: replace with char *!)
+   */
+  GCG_PHONE_LS_CALLER_STATE,
+
+  /**
+   * A `struct OutgoingCall *`.
+   */
+  GCG_PHONE_LS_CALL,
+
+  /**
+   * A `gint` for a `enum OutCallState` (FIXME: replace with char *,
+   * combine with #GCG_PHONE_LS_CALLER_STATE).
+   */
+  GCG_PHONE_LS_CALL_STATE,
+
+  /**
+   * A `gint`.  FIXME: combine with #GCG_PHONE_LS_CALLER_NUM!
+   */
+  GCG_PHONE_LS_CALL_NUM
+
 };
 
 
 /**
- * type of call
+ * Types of conversations
  */
-enum TypeOfCall
+enum TypeOfConversation
 {
+  /**
+   * Incoming phone call.
+   */
   CALL_IN,
+
+  /**
+   * Outgoing call.
+   */
   CALL_OUT
 };
 
@@ -79,7 +104,7 @@
 enum PhoneState
 {
   /**
-   * We're waiting for our own idenitty.
+   * We're waiting for the user to select a caller ID.
    */
   PS_LOOKUP_EGO,
 
@@ -101,83 +126,133 @@
 
 
 /**
- * States for current outgoing call.
+ * States for current incoming call.
  */
-enum CallState
+enum InCallState
 {
   /**
-   * We are looking up some other participant.
+   * No incoming call.
    */
-  CS_RESOLVING,
+  IN_STATE_NONE,
 
   /**
-   * We are now ringing the other participant.
+   * Our phone is ringing.
    */
-  CS_RINGING,
+  IN_STATE_RINGING,
 
   /**
    * The other party accepted our call and we are now connected.
    */
-  CS_CONNECTED,
+  IN_STATE_CONNECTED,
 
   /**
    * The call is currently suspended (by us).
    */
-  CS_SUSPENDED
+  IN_STATE_SUSPENDED
 };
 
 
-
 /**
- * List of incoming calls
+ * Possible states of outgoing phone calls.
  */
-struct CallList
+enum OutCallState
 {
+  /**
+   * Phone state we use if this is not an outgoing call.
+   */
+  OUT_STATE_NONE,
 
   /**
-   * A DLL.
+   * This phone call is currently resolving.
    */
-  struct CallList *prev;
+  OUT_STATE_RESOLVING,
 
   /**
-   * A DLL.
+   * This phone call is currently ringing.
    */
-  struct CallList *next;
+  OUT_STATE_RINGING,
 
   /**
-   * Handle to hang up or activate.
+   * This phone call is currently active.
    */
-  struct GNUNET_CONVERSATION_Caller *caller;
+  OUT_STATE_ACTIVE,
 
   /**
-   * Handle to call currently selected in list
+   * This phone call is currently suspended.
    */
-  struct GNUNET_CONVERSATION_Caller *caller_selected;
+  OUT_STATE_SUSPENDED
 
+};
+
+
+/**
+ * List of incoming calls
+ */
+struct IncomingCall
+{
+
   /**
+   * Handle to hang up or activate.
+   */
+  struct GNUNET_CONVERSATION_Caller *caller;
+
+  /**
    * String identifying the caller.
    */
   char *caller_id;
 
   /**
+   * Location of this call in the list.
+   */
+  GtkTreeRowReference *rr;
+
+  /**
    * Unique number of the caller.
    */
   unsigned int caller_num;
 
+  /**
+   * State for this call.
+   */
+  enum InCallState state;
+
 };
 
 
 /**
- *
+ * Information we keep for an outgoing call.
  */
-static struct GNUNET_CONVERSATION_Caller *caller_selected;
+struct OutgoingCall
+{
 
-/**
- *
- */
-static struct GNUNET_CONVERSATION_Call *call_selected;
+  /**
+   * Associated conversation handle.
+   */
+  struct GNUNET_CONVERSATION_Call *call;
 
+  /**
+   * Name of conversation partner.
+   */
+  char *peer_name;
 
+  /**
+   * Location of this call in the list.
+   */
+  GtkTreeRowReference *rr;
+
+  /**
+   * Unique number of the caller.
+   */
+  unsigned int caller_num;
+
+  /**
+   * State for this call.
+   */
+  enum OutCallState state;
+
+};
+
+
 /**
  * List of active calls
  */
@@ -189,84 +264,91 @@
 static GtkTreeView *active_treeview;
 
 /**
- * Unique number of call (outgoing)
+ * Phone handle
  */
-static unsigned int call_counter;
+static struct GNUNET_CONVERSATION_Phone *phone;
 
 /**
- * Counts the number of incoming calls we have had so far.
+ * Our speaker.
  */
-static unsigned int caller_num_gen;
+static struct GNUNET_SPEAKER_Handle *speaker;
 
 /**
- * Phone handle
+ * Our microphone.
  */
-static struct GNUNET_CONVERSATION_Phone *phone;
+static struct GNUNET_MICROPHONE_Handle *mic;
 
 /**
- * Call handle (for active outgoing call).
+ * Our phone's current state.
  */
-static struct GNUNET_CONVERSATION_Call *call;
+static enum PhoneState phone_state;
 
+
 /**
- * Caller handle (for active incoming call).
+ * Counts the number of incoming calls we have had so far.
  */
-static struct CallList *cl_active;
+static unsigned int caller_num_gen;
 
 /**
- * Head of calls waiting to be accepted.
+ * Unique number of call (outgoing)
  */
-static struct CallList *cl_head;
+static unsigned int call_counter;
 
 /**
- * Tail of calls waiting to be accepted.
+ * Number of incoming calls that are currently ringing.
  */
-static struct CallList *cl_tail;
+static unsigned int in_ring_counter;
 
 /**
- * Our speaker.
+ * Caller handle (for active incoming call, or NULL).
  */
-static struct GNUNET_SPEAKER_Handle *speaker;
+static struct IncomingCall *active_in;
 
 /**
- * Our microphone.
+ * Call handle (of the active outgoing call, or NULL).
  */
-static struct GNUNET_MICROPHONE_Handle *mic;
+static struct OutgoingCall *active_out;
 
+
 /**
- * Our phone's current state.
+ * The "add contact" (or "> contact") button.
  */
-static enum PhoneState phone_state;
+static GtkWidget *b_add_contact;
 
 /**
- * Our call's current state.
+ * The "accept" button.
  */
-static enum CallState call_state;
+static GtkWidget *b_accept;
 
 /**
- * Name of conversation partner (if any).
+ * The "refuse" button.
  */
-static char *peer_name;
+static GtkWidget *b_refuse;
 
 /**
- * GNS address for this phone.
+ * The "pause" button.
  */
-static char *address;
+static GtkWidget *b_suspend;
 
-static GtkWidget *b_add_contact;
-
-static GtkWidget *b_accept;
-
-static GtkWidget *b_refuse;
-
-static GtkWidget *b_suspend; // pause
-
+/**
+ * The "resume" button.
+ */
 static GtkWidget *b_resume;
 
-static GtkWidget *b_call; // connect
+/**
+ * The "connect" button.
+ */
+static GtkWidget *b_call;
 
-static GtkWidget *b_hangup; // disconnect up
+/**
+ * The "disconnect" button.
+ */
+static GtkWidget *b_hangup;
 
+/**
+ * Our address entry.
+ */
+static GtkEntry *address_entry;
 
 
 /**
@@ -277,452 +359,129 @@
 static void
 do_status ()
 {
-  switch (phone_state)
+  if ( (NULL == active_in) &&
+       (NULL == active_out) &&
+       (0 != in_ring_counter) )
   {
-  case PS_LOOKUP_EGO:
+    GCG_update_status_bar (_("The phone is ringing (%u calls waiting)"),
+                           in_ring_counter);
+    GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-incoming");
+    return;
+  }
+  if ( (NULL == active_in) &&
+       (NULL == active_out) &&
+       (PS_LISTEN == phone_state) )
+  {
     GCG_update_status_bar ("%s",
-                       _("Phone inactive: no ego selected for the caller 
ID."));
-    GCG_set_status_icon ("gnunet-conversation-gtk-tray-pending");
-    break;
-  case PS_LISTEN:
-    GCG_update_status_bar ("%s",
-                       _("We are listening for incoming calls"));
+                           _("We are listening for incoming calls"));
     GCG_set_status_icon ("gnunet-conversation-gtk-tray-available");
-    break;
-  case PS_ACCEPTED:
-    GCG_update_status_bar (_("You are having a conversation with `%s'.\n"),
-                       peer_name);
-    GCG_set_status_icon ("gnunet-conversation-call-active");
-    break;
-  case PS_ERROR:
-    GCG_update_status_bar (_("We had an internal error setting up our phone 
line. You can still make calls."));
-    GCG_set_status_icon ("gnunet-conversation-offline");
-    break;
   }
-  if (NULL != call)
-  {
-    switch (call_state)
-    {
-    case CS_RESOLVING:
-      GCG_update_status_bar (_("We are trying to find the network address to 
call `%s'."),
-                         peer_name);
-      GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-pending");
-      break;
-    case CS_RINGING:
-      GCG_update_status_bar (_("We are calling `%s', his phone should be 
ringing."),
-                         peer_name);
-      GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-ringing");
-      break;
-    case CS_CONNECTED:
-      GCG_update_status_bar (_("You are having a conversation with `%s'."),
-                         peer_name);
-      GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-active");
-      break;
-    case CS_SUSPENDED:
-      GCG_update_status_bar (_("Conversation suspended, you can accept or 
initiate another call now."),
-                         peer_name);
-      GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-suspended");
-      break;
-    }
-  }
-  if ( ( (NULL == call) ||
-         (CS_SUSPENDED == call_state) ) &&
-       (NULL != cl_head) &&
-       ( (cl_head != cl_active) ||
-         (cl_head != cl_tail) ) )
-    GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-incoming");
 }
 
 
-
 /**
- * @brief print info for currently selected call
+ * Check if the conditions are met for the "call" button to
+ * be sensitive again.  Those conditions are that we must
+ * have a phone that is ready to "listen" (no error or active
+ * call), and that some address text is in the address entry.
  */
 static void
-print_call_info ()
+check_call_sensitivity ()
 {
-  GtkTreeIter gtkiter;
-  gboolean valid;
-  gint row_count = 0;
+  gboolean sens;
 
-  valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (active_liststore),
-                                         &gtkiter);
-  if (! valid)
-    GNUNET_break(0);
-
-  while (valid)
-  {
-    gchar *str_data;
-    gint   int_data;
-    gpointer cl_caller;
-    gpointer cl_call;
-
-    gtk_tree_model_get (GTK_TREE_MODEL (active_liststore),
-                        &gtkiter,
-                        AL_caller,     &cl_caller,
-                        AL_caller_id,  &str_data,
-                        AL_caller_num, &int_data,
-                        AL_call,       &cl_call,
-                        -1);
-    if (call_selected == cl_call)
-    {
-      GCG_log (_("info for active outgoing call:%s number: %u row: %u"),
-               str_data,
-               int_data,
-               row_count);
-      break;
-    }
-    g_free (str_data);
-    row_count++;
-    valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(active_liststore), 
&gtkiter);
-  }
+  sens = (PS_LISTEN == phone_state);
+  if (0 == strlen (gtk_entry_get_text (address_entry)))
+    sens = FALSE;
+  gtk_widget_set_sensitive (b_call, sens);
 }
 
 
 /**
- * @brief sets caller_selected, and enables or disables the active call list 
buttons
- */
-static void
-update_active_call_list_buttons ()
-{
-  gchar *caller_id;
-  gpointer cl_caller;
-  gpointer cl_call;
-  gint     cl_caller_state;
-  gint     cl_type;
-  //gint     cl_caller_type;
-  GtkTreeSelection *active_selection;
-  GtkTreeIter gcl_selected;
-  //   active_liststore_selection = 
GCG_get_main_window_object(ml,"GNUNET_CONVERSATION_GTK_active_calls_selection");
-
-  // reset references to selected call/caller
-  //caller_selected = NULL;
-  //call_selected = NULL;
-  GCG_log("reset caller selected");
-  active_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW 
(active_treeview));
-  if (gtk_tree_selection_get_selected (active_selection,
-                                       NULL,
-                                       &gcl_selected))
-  {
-    // get selected call
-    gtk_tree_model_get (GTK_TREE_MODEL(active_liststore), &gcl_selected,
-                        AL_caller, &cl_caller, // reference to incoming call
-                        AL_caller_id, &caller_id,
-                        AL_caller_state, &cl_caller_state,
-                        AL_type, &cl_type,
-                        AL_call, &cl_call, // reference to outgoing call
-                        -1);
-    // check if selected call is a incoming or outgoing call
-    switch (cl_type)
-    {
-    case CALL_IN:
-      call_selected = NULL;
-      caller_selected = cl_caller;
-      GNUNET_break (NULL != caller_selected);
-      break;
-    case CALL_OUT:
-      caller_selected = NULL;
-      call_selected = cl_call;
-      GCG_log("outgoing selected");
-      GNUNET_break (NULL != call_selected);
-      break;
-    default:
-      GNUNET_break(0);
-      break;
-    }
-    
gtk_widget_show(GTK_WIDGET(GCG_get_main_window_object("GNUNET_GTK_conversation_active_call_list_buttons")));
-    GCG_log("caller state: %u phone_state: %u",
-            cl_caller_state,
-            phone_state);
-    switch (cl_caller_state)
-    {
-      /* buttons:
-       *  contact
-       *  accept
-       *  hangup
-       *  suspend
-       *  resume
-       *
-       *  TODO: check if there is incoming or outgoing call,
-       *         disable resume and accept buttons.
-       *         or suspend that other call
-       */
-    case CT_active:
-      // hangup, pause
-      //GCG_log("CT_active state: %u ",cl_caller_state);
-      gtk_widget_set_sensitive (b_add_contact, TRUE);
-      gtk_widget_set_sensitive (b_accept, FALSE);
-      gtk_widget_set_sensitive (b_hangup, TRUE);
-      gtk_widget_set_sensitive (b_suspend, TRUE);
-      gtk_widget_set_sensitive (b_resume, FALSE);
-      break;
-    case CT_ringing:
-      // pickup, phonebook
-      //GCG_log("CT_ring show button");
-      gtk_widget_set_sensitive (b_add_contact, TRUE);
-      if (phone_state == PS_LISTEN)
-      {
-        gtk_widget_set_sensitive (b_accept, TRUE);
-      }
-      else
-      {
-        gtk_widget_set_sensitive (b_accept, FALSE);
-      }
-      gtk_widget_set_sensitive (b_hangup, FALSE);
-      gtk_widget_set_sensitive (b_suspend, FALSE);
-      gtk_widget_set_sensitive (b_resume, FALSE);
-      break;
-    case CT_rejected:
-      //add to phonebook
-      //GCG_log("CT_rejected ");
-      gtk_widget_set_sensitive (b_add_contact, TRUE);
-      gtk_widget_set_sensitive (b_accept, FALSE);
-      gtk_widget_set_sensitive (b_hangup, FALSE);
-      gtk_widget_set_sensitive (b_suspend, FALSE);
-      gtk_widget_set_sensitive (b_resume, FALSE);
-      break;
-    case CT_suspended:
-      // resume, hangup
-      //GCG_log("CT_suspended ");
-      gtk_widget_set_sensitive (b_add_contact, TRUE);
-      gtk_widget_set_sensitive (b_accept, FALSE);
-      gtk_widget_set_sensitive (b_hangup, TRUE);
-      gtk_widget_set_sensitive (b_suspend, FALSE);
-      if (phone_state == PS_LISTEN)
-      {
-        GCG_log("enable resume button");
-        gtk_widget_set_sensitive (b_resume, TRUE);
-      }
-      else
-      {
-        GCG_log("do not disable resume button (for test)");
-        gtk_widget_set_sensitive (b_resume, TRUE);
-      }
-      break;
-    case CT_other:
-      //add to phonebook
-      //GCG_log("CT_rejected ");
-      gtk_widget_set_sensitive (b_add_contact, TRUE);
-      gtk_widget_set_sensitive (b_accept, TRUE);
-      gtk_widget_set_sensitive (b_hangup, TRUE);
-      gtk_widget_set_sensitive (b_suspend, TRUE);
-      gtk_widget_set_sensitive (b_resume, TRUE);
-      break;
-
-    default:
-      GNUNET_break(0);
-      break;
-    }
-    print_call_info();
-  }
-  else
-  {
-    GCG_log("nothing selected");
-    
//gtk_widget_hide(GTK_WIDGET(GCG_get_main_window_object("GNUNET_GTK_conversation_active_call_list_buttons"
 )));
-  }
-}
-
-
-/**
  * @brief executed when selecting a different item in active call list
  */
 void
 gnunet_conversation_gtk_active_calls_treeview_selection_changed_cb ()
 {
-  update_active_call_list_buttons();
+  // FIXME
 }
 
 
-static void
-disable_list_buttons ()
-{
-  gtk_widget_set_sensitive (b_add_contact, FALSE);
-  gtk_widget_set_sensitive (b_accept, FALSE);
-  gtk_widget_set_sensitive (b_hangup, FALSE);
-  gtk_widget_set_sensitive (b_suspend, FALSE);
-  gtk_widget_set_sensitive (b_resume, FALSE);
-}
-
-
 /**
- * set state of outgoing call
+ * Set state of outgoing call.
+ *
+ * @param oc outgoing call to change state of
+ * @param state new state of the call
  */
 static void
-set_outgoing_call_state (struct GNUNET_CONVERSATION_Call *call,
-                         int state)
+set_outgoing_call_state (struct OutgoingCall *oc,
+                         enum OutCallState state)
 {
-  GtkTreeIter gtkiter;
-  gint valid = 0;
-  gint cl_type;
+  GtkTreePath *path;
+  GtkTreeIter iter;
 
-  valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (active_liststore),
-                                         &gtkiter);
-  if (!valid)
-    GNUNET_break(0);
-  while (valid)
+  path = gtk_tree_row_reference_get_path (oc->rr);
+  GNUNET_assert (gtk_tree_model_get_iter (GTK_TREE_MODEL (active_liststore),
+                                          &iter,
+                                          path));
+  gtk_tree_path_free (path);
+  switch (state)
   {
-    gchar *cl_caller_id;
-    gint   cl_caller_num;
-    gpointer cl_call;
-
-    gtk_tree_model_get ( GTK_TREE_MODEL( active_liststore ), &gtkiter,
-                         AL_call, &cl_call,
-                         AL_caller_id,&cl_caller_id,
-                         AL_caller_num,&cl_caller_num,
-                         AL_type, &cl_type,
-                         -1);
-    if (cl_type == CALL_OUT)
-    {
-      if (call == NULL) // function called by phone event handler
-      {
-        GCG_log("event handler");
-        gtk_list_store_set(active_liststore, &gtkiter,
-                           AL_call_state, state,
-                           -1);
-        switch (state)
-        {
-          /**
-           * We are the caller and are now ringing the other party (GNS lookup
-           * succeeded).
-           */
-        case  GNUNET_CONVERSATION_EC_CALL_RINGING:
-          break;
-          /**
-           * We are the caller and are now ready to talk as the callee picked 
up.
-           */
-        case GNUNET_CONVERSATION_EC_CALL_PICKED_UP:
-          break;
-          /**
-           * We are the caller and failed to locate a phone record in GNS.
-           * After this invocation, the respective call handle will be
-           * automatically destroyed and the client must no longer call
-           * #GNUNET_CONVERSATION_call_stop or any other function on the
-           * call object.
-           */
-        case GNUNET_CONVERSATION_EC_CALL_GNS_FAIL:
-           gtk_list_store_remove(active_liststore,&gtkiter);
-           disable_list_buttons();
-           break;
-          /**
-           * We are the caller and the callee called
-           * #GNUNET_CONVERSATION_caller_hang_up.  After this invocation, the
-           * respective call handle will be automatically destroyed and the
-           * client must no longer call #GNUNET_CONVERSATION_call_stop.
-           */
-        case GNUNET_CONVERSATION_EC_CALL_HUNG_UP:
-          gtk_list_store_remove(active_liststore,&gtkiter);
-          disable_list_buttons();
-          break;
-          /**
-           * We are the caller and the callee suspended the call.  Note that
-           * both sides can independently suspend and resume calls; a call is
-           * only "working" of both sides are active.
-           */
-        case GNUNET_CONVERSATION_EC_CALL_SUSPENDED:
-          break;
-          /**
-           * We are the caller and the callee suspended the call.  Note that
-           * both sides can independently suspend and resume calls; a call is
-           * only "working" of both sides are active.
-           */
-        case GNUNET_CONVERSATION_EC_CALL_RESUMED:
-          break;
-          /**
-           * We had an error handing the call, and are now restarting it
-           * (back to lookup).  This happens, for example, if the peer
-           * is restarted during a call.
-           */
-        case GNUNET_CONVERSATION_EC_CALL_ERROR:
-          break;
-        default:
-          break;
-        }
-      }
-      else if (call == cl_call) // function called for specific call
-      {
-        //GCG_log (_("setting state for call:%u row: %u state: 
%u"),cl_caller_num,row_count,state);
-
-        switch (state)
-        {
-        case CT_hangup:
-          //GCG_log("remove line cause hangup");
-          gtk_list_store_remove(active_liststore,&gtkiter);
-          disable_list_buttons();
-          break;
-        case CT_rejected:
-          //GCG_log("remove line cause rejected");
-          gtk_list_store_remove(active_liststore,&gtkiter);
-          disable_list_buttons();
-          break;
-        default:
-          gtk_list_store_set(active_liststore, &gtkiter,
-                             AL_caller_state, state,
-                             -1);
-          break;
-        }
-      }
-    }
-    g_free (cl_caller_id);
-    valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(active_liststore), 
&gtkiter);
+  case OUT_STATE_NONE:
+    gtk_list_store_remove (active_liststore,
+                           &iter);
+    return;
+  case OUT_STATE_RESOLVING:
+    break;
+  case OUT_STATE_RINGING:
+    break;
+  case OUT_STATE_ACTIVE:
+    break;
+  case OUT_STATE_SUSPENDED:
+    break;
   }
-  GCG_update_status_bar ("");
+  gtk_list_store_set (active_liststore,
+                      &iter,
+                      GCG_PHONE_LS_CALL_STATE, state,
+                      -1);
 }
 
 
 /**
- * set call state of a incoming call
+ * Set call state of a incoming call
+ *
+ * @param ic incoming call to change state of
+ * @param state new state of the call
  */
 static void
-set_incoming_call_state (struct GNUNET_CONVERSATION_Caller *caller,
-                         int state)
+set_incoming_call_state (struct IncomingCall *ic,
+                         enum InCallState state)
 {
-  GtkTreeIter gtkiter;
-  gint valid = 0;
+  GtkTreePath *path;
+  GtkTreeIter iter;
 
-  valid = gtk_tree_model_get_iter_first( GTK_TREE_MODEL( active_liststore ), 
&gtkiter );
-  if (!valid)
-    GNUNET_break(0);
-  while (valid)
+  path = gtk_tree_row_reference_get_path (ic->rr);
+  GNUNET_assert (gtk_tree_model_get_iter (GTK_TREE_MODEL (active_liststore),
+                                          &iter,
+                                          path));
+  gtk_tree_path_free (path);
+  switch (state)
   {
-    gchar *cl_caller_id;
-    gint   cl_caller_num;
-    gpointer cl_caller;
-
-    gtk_tree_model_get (GTK_TREE_MODEL (active_liststore ),
-                        &gtkiter,
-                        AL_caller, &cl_caller,
-                        AL_caller_id, &cl_caller_id,
-                        AL_caller_num, &cl_caller_num,
-                        -1);
-    if (caller == cl_caller)
-    {
-      switch (state)
-      {
-      case CT_hangup:
-        //GCG_log("remove line cause hangup");
-        gtk_list_store_remove (active_liststore,
-                               &gtkiter);
-        disable_list_buttons ();
-        break;
-      case CT_rejected:
-        //GCG_log("remove line cause rejected");
-        gtk_list_store_remove (active_liststore,
-                               &gtkiter);
-        disable_list_buttons ();
-        break;
-      default:
-        gtk_list_store_set (active_liststore,
-                            &gtkiter,
-                            AL_caller_state, state,
-                            -1);
-        break;
-      }
-    }
-    g_free (cl_caller_id);
-    valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(active_liststore),
-                                      &gtkiter);
+  case IN_STATE_NONE:
+    gtk_list_store_remove (active_liststore,
+                           &iter);
+    return;
+  case IN_STATE_RINGING:
+    break;
+  case IN_STATE_CONNECTED:
+    break;
+  case IN_STATE_SUSPENDED:
+    break;
   }
-  GCG_update_status_bar("");
+  gtk_list_store_set (active_liststore,
+                      &iter,
+                      GCG_PHONE_LS_CALLER_STATE, state,
+                      -1);
 }
 
 
@@ -740,61 +499,59 @@
                      struct GNUNET_CONVERSATION_Caller *caller,
                      const char *caller_id)
 {
-  GtkTreeIter gtkiter;
-  GtkTreeIter gtkiter1;
+  GtkTreeIter iter;
   gboolean valid;
-  struct CallList *cl;
+  struct IncomingCall *ic;
 
   switch (code)
   {
   case GNUNET_CONVERSATION_EC_PHONE_RING:
-    caller_num_gen++;
+    ic = GNUNET_new (struct IncomingCall);
+    ic->caller = caller;
+    ic->caller_id = GNUNET_strdup (caller_id);
+    ic->caller_num = caller_num_gen++;
+    gtk_list_store_insert_with_values (active_liststore,
+                                       &iter,
+                                       -1,
+                                       GCG_PHONE_LS_CALLER_ID, caller_id,
+                                       GCG_PHONE_LS_CALLER, ic,
+                                       GCG_PHONE_LS_CALLER_NUM, caller_num_gen,
+                                       GCG_PHONE_LS_CALLER_STATE, 
IN_STATE_RINGING,
+                                       GCG_PHONE_LS_TYPE, CALL_IN,
+                                       -1);
+    // FIXME: initialize ic->rr
     GCG_log (_("A Incoming call from `%s' with number %u\n"),
              caller_id,
              caller_num_gen);
-    cl = GNUNET_new (struct CallList);
-    cl->caller = caller;
-    cl->caller_id = GNUNET_strdup (caller_id);
-    cl->caller_num = caller_num_gen;
-    GNUNET_CONTAINER_DLL_insert (cl_head, cl_tail, cl);
-    gtk_list_store_append (active_liststore,
-                           &gtkiter);
-    gtk_list_store_set (active_liststore,
-                        &gtkiter,
-                        AL_caller_id, caller_id,
-                        AL_caller, caller,
-                        AL_caller_num, caller_num_gen,
-                        AL_caller_state, CT_ringing,
-                        AL_type, CALL_IN,
-                        -1);
     break;
   case GNUNET_CONVERSATION_EC_PHONE_HUNG_UP:
-    valid = gtk_tree_model_get_iter_first( GTK_TREE_MODEL( active_liststore ), 
&gtkiter1 );
-    if (!valid)
-      GNUNET_break(0);
+    valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (active_liststore),
+                                           &iter);
+    GNUNET_break (valid);
     while (valid)
     {
       gchar *str_data;
       gint   int_data;
-      gpointer cl_caller;
+      struct IncomingCall *ic;
 
-      gtk_tree_model_get (GTK_TREE_MODEL(active_liststore),
-                          &gtkiter1,
-                          AL_caller, &cl_caller,
-                          AL_caller_id, &str_data,
-                          AL_caller_num, &int_data,
+      gtk_tree_model_get (GTK_TREE_MODEL (active_liststore),
+                          &iter,
+                          GCG_PHONE_LS_CALLER, &ic,
+                          GCG_PHONE_LS_CALLER_ID, &str_data,
+                          GCG_PHONE_LS_CALLER_NUM, &int_data,
                           -1);
-      if (caller == cl_caller)
+      if (caller == ic->caller)
       {
         GCG_log (_("phone hung up:%s number: %u "),
                  str_data,
                  int_data);
-        set_incoming_call_state (caller,
-                                 CT_rejected);
+        set_incoming_call_state (ic,
+                                 IN_STATE_NONE);
         break;
       }
       g_free (str_data);
-      valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(active_liststore), 
&gtkiter1);
+      valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (active_liststore),
+                                        &iter);
     }
     phone_state = PS_LISTEN;
     break;
@@ -813,7 +570,7 @@
 caller_event_handler (void *cls,
                       enum GNUNET_CONVERSATION_CallerEventCode code)
 {
-  struct CallList *cl = cls;
+  struct IncomingCall *cl = cls;
 
   if (NULL == cl)
   {
@@ -824,12 +581,16 @@
   {
   case GNUNET_CONVERSATION_EC_CALLER_SUSPEND:
     //TODO: should this be cls? not cl->caller
-    set_incoming_call_state(cl->caller,CT_suspended);
-    GCG_log (_("Call from `%s' suspended by other user\n"), cl->caller_id);
+    set_incoming_call_state (cl,
+                             IN_STATE_SUSPENDED);
+    GCG_log (_("Call from `%s' suspended by other user\n"),
+             cl->caller_id);
     break;
   case GNUNET_CONVERSATION_EC_CALLER_RESUME:
-    set_incoming_call_state(cl->caller,CT_active);
-    GCG_log (_("Call from `%s' resumed by other user\n"), cl->caller_id);
+    set_incoming_call_state(cl,
+                            IN_STATE_CONNECTED);
+    GCG_log (_("Call from `%s' resumed by other user\n"),
+             cl->caller_id);
     break;
   }
   do_status();
@@ -837,264 +598,175 @@
 
 
 /**
- * Start our phone.
+ * The "accept" button was clicked.  Accept selected incoming call.
+ *
+ * @param button the button
+ * @param user_data builder (unused)
  */
-static void
-start_phone ()
+void
+GNUNET_CONVERSATION_GTK_on_accept_clicked (GtkButton *button,
+                                           gpointer user_data)
 {
-  struct GNUNET_GNSRECORD_Data rd;
-  struct GNUNET_IDENTITY_Ego *caller_id;
+  struct IncomingCall *ic;
 
-  caller_id = GCG_EGOS_get_selected_ego ();
-  if (NULL == caller_id)
+  if ( (NULL != active_in) ||
+       (NULL != active_out) ||
+       (PS_LISTEN != phone_state) )
   {
-    GCG_log ("%s\n",
-             _("No ego selected, phone is now down."));
-    phone_state = PS_LOOKUP_EGO;
-    do_status();
+    /* accept button should not have been sensitive! */
+    GNUNET_break (0);
     return;
   }
-  phone =
-    GNUNET_CONVERSATION_phone_create (GCG_get_configuration (),
-                                      caller_id,
-                                      &phone_event_handler,
-                                      NULL);
-  if (NULL == phone)
-  {
-    GCG_log ("%s",
-             _("Failed to setup phone (internal error)\n"));
-    phone_state = PS_ERROR;
-    do_status();
-    return;
-  }
-  GNUNET_CONVERSATION_phone_get_record (phone,
-                                        &rd);
-  /* FIXME: publish record to GNS! */
-  GCG_log ("%s\n",
-           _("Phone active"));
-  phone_state = PS_LISTEN;
-  do_status();
+  phone_state = PS_ACCEPTED;
+  ic = NULL; // FIXME: get 'ic' from selection!
+  set_incoming_call_state (ic,
+                           IN_STATE_CONNECTED);
+  GCG_update_status_bar (_("Started a conversation with `%s'.\n"),
+                         ic->caller_id);
+  GCG_set_status_icon ("gnunet-conversation-call-active");
+  GNUNET_CONVERSATION_caller_pick_up (ic->caller,
+                                      &caller_event_handler, ic,
+                                      speaker, mic);
+  GCG_HISTORY_add (GCG_HISTORY_TYPE_ACCEPTED,
+                   ic->caller_id);
+  // FIXME: update visibility properly...
+  do_status ();
 }
 
 
 /**
- * Function called with an event emitted by a call.
+ * The "reject" button was clicked.  Reject incoming call.
  *
- * @param cls closure, NULL
- * @param code type of the event on the call
+ * @param button the button
+ * @param user_data builder (unused)
  */
-static void
-call_event_handler (void *cls,
-                    enum GNUNET_CONVERSATION_CallEventCode code)
+void
+GNUNET_CONVERSATION_GTK_on_reject_clicked (GtkButton *button,
+                                           gpointer user_data)
 {
-  //struct OutgoingCallClosure *cl = cls;
-
-  set_outgoing_call_state (NULL, code);
-  switch (code)
-  {
-  case GNUNET_CONVERSATION_EC_CALL_RINGING:
-    GNUNET_break (CS_RESOLVING == call_state);
-    GCG_log (_("Resolved address of `%s'. Now ringing other party."),
-             peer_name);
-    //   set_outgoing_call_state(cls, CT_ringing);
-    call_state = CS_RINGING;
-    break;
-  case GNUNET_CONVERSATION_EC_CALL_PICKED_UP:
-    GNUNET_break (CS_RINGING == call_state);
-    GCG_log (_("Connection established to `%s'."),
-             peer_name);
-    call_state = CS_CONNECTED;
-    break;
-  case GNUNET_CONVERSATION_EC_CALL_GNS_FAIL:
-    GNUNET_break (CS_RESOLVING == call_state);
-    GCG_log (_("Failed to resolve %s in current zone."),
-             peer_name);
-    call = NULL;
-    break;
-  case GNUNET_CONVERSATION_EC_CALL_HUNG_UP:
-    GCG_log ("%s", _("Call terminated"));
-    call = NULL;
-    break;
-  case GNUNET_CONVERSATION_EC_CALL_SUSPENDED:
-    GNUNET_break (CS_CONNECTED == call_state);
-    GCG_log (_("Connection to `%s' suspended (by other user)\n"),
-             peer_name);
-    break;
-  case GNUNET_CONVERSATION_EC_CALL_RESUMED:
-    GNUNET_break (CS_CONNECTED == call_state);
-    GCG_log (_("Connection to `%s' resumed (by other user)\n"),
-             peer_name);
-    break;
-  case GNUNET_CONVERSATION_EC_CALL_ERROR:
-    GCG_log ("GNUNET_CONVERSATION_EC_CALL_ERROR %s",
-             peer_name);
-  }
+  //  do_reject (); // FIXME!
+  do_status ();
 }
 
 
 /**
- * Initiating a new call
+ * User clicked the '> contact' button to move the selected
+ * caller's information into our address book.
  *
- * @param arg arguments given to the command
+ * @param button the button
+ * @param user_data builder (unused)
  */
 void
-GSC_PHONE_make_call (const char *arg)
+GNUNET_CONVERSATION_GTK_use_current_button_clicked (GtkButton *button,
+                                                    gpointer *user_data)
 {
-  GtkEntry *address_entry;
-  struct GNUNET_IDENTITY_Ego *caller_id;
-  GtkTreeIter gtkiter;
+  // FIXME: implement, use "GSC_add_contact"
+#if 0
+  const gchar *target;
 
-  address_entry = GTK_ENTRY (GCG_get_main_window_object 
("GNUNET_GTK_conversation_address"));
+  target = gtk_entry_get_text (address_entry);
   gtk_entry_set_text (address_entry,
-                      address);
-  caller_id = GCG_EGOS_get_selected_ego ();
-  if (NULL == caller_id)
-  {
-    // should not be possible!
-    GCG_log ("%s\n",
-             _("Caller ID unavailable, cannot initiate call."));
-    return;
-  }
-  if (NULL != call)
-  {
-    GCG_log (_("You are calling someone else already, hang up first!\n"));
-    return;
-  }
-  switch (phone_state)
-  {
-  case PS_LOOKUP_EGO:
-    GCG_log ("%s\n",
-             _("Caller ID unavailable, cannot initiate call."));
-    // should not be possible!
-    return;
-  case PS_LISTEN:
-    /* ok to call! */
-    break;
-  case PS_ACCEPTED:
-    GCG_log (_
-         ("You are answering call from `%s', hang up or suspend that call 
first!\n"),
-         peer_name);
-    GNUNET_break(0);
-    return;
-  case PS_ERROR:
-    /* ok to call */
-    break;
-  }
-  //GNUNET_free_non_null (peer_name);
-  peer_name = GNUNET_strdup (arg);
-  GCG_log (_("now calling: %s"), peer_name);
-  call_state = CS_RESOLVING;
-  GNUNET_assert (NULL == call);
-
-  call_counter++;
-  call =
-     GNUNET_CONVERSATION_call_start (GCG_get_configuration (),
-                                     caller_id,
-                                     arg,
-                                     speaker, mic,
-                                     &call_event_handler, NULL);
-  //call = newcall;
-
-  // add call to active call list
-
-  gtk_list_store_append (active_liststore,
-                         &gtkiter);
-  gtk_list_store_set (active_liststore, &gtkiter,
-                      AL_caller_id, peer_name,
-                      AL_caller, NULL,
-                      AL_caller_num, NULL,
-                      AL_caller_state, CT_other,
-                      AL_type, CALL_OUT,
-                      AL_call, call,
-                      AL_call_num, call_counter,
-                      AL_call_state, CS_RESOLVING,
-                      -1 );
-  GCG_update_status_bar (_("We are calling `%s', his phone should be 
ringing."),
-                         peer_name);
-  GCG_HISTORY_add (GCG_HISTORY_TYPE_OUTGOING,
-                   peer_name);
+                      "FIXME");
+#endif
 }
 
 
 /**
- * Accepting an incoming call
+ * The "resume" button was clicked.  Resume a call!
  *
- * @param args arguments given to the command
+ * @param button the button
+ * @param user_data builder (unused)
  */
-static void
-do_accept (struct GNUNET_CONVERSATION_Caller *sel_caller)
+void
+GNUNET_CONVERSATION_GTK_on_resume_clicked (GtkButton *button,
+                                           gpointer user_data)
 {
-  struct CallList *cl;
+  enum TypeOfConversation toc;
+  struct IncomingCall *ic;
+  struct OutgoingCall *oc;
 
-  if ( (NULL != call) &&
-       (CS_SUSPENDED != call_state) )
+  if ( (NULL != active_in) ||
+       (NULL != active_out) ||
+       (! (PS_LISTEN == phone_state) ||
+          (PS_ERROR == phone_state) ) )
   {
-    GCG_log (_("You are calling someone else already, hang up first!\n"));
+    /* resume button should have been inactive */
     GNUNET_break(0);
     return;
   }
-  switch (phone_state)
+  toc = 42; // FIXME: get from selection!
+
+  switch (toc)
   {
-  case PS_LOOKUP_EGO:
-    GNUNET_break (0);
-    break;
-  case PS_LISTEN:
-    /* this is the expected state */
-    break;
-  case PS_ACCEPTED:
-    GCG_log (_
-         ("You are answering call from `%s', hang up or suspend that call 
first!\n"),
-         peer_name);
-    GNUNET_break(0);
+  case CALL_IN:
+    ic = NULL; // FIXME: get from selection
+    GNUNET_CONVERSATION_caller_resume (ic->caller, speaker, mic);
+    set_incoming_call_state (ic, IN_STATE_CONNECTED);
+    phone_state = PS_ACCEPTED;
+    GCG_update_status_bar (_("Resumed a conversation with `%s'.\n"),
+                           ic->caller_id);
+    GCG_set_status_icon ("gnunet-conversation-call-active");
+    // FIXME: update visibility/sensitivity
+    do_status ();
     return;
-  case PS_ERROR:
-    GNUNET_break (0);
-    break;
+  case CALL_OUT:
+    oc = NULL; // FIXME: get from selection
+    GNUNET_CONVERSATION_call_resume (oc->call,
+                                     speaker, mic);
+    set_outgoing_call_state (oc,
+                             OUT_STATE_ACTIVE);
+    // FIXME: update visibility/sensitivity
+    do_status ();
+    return;
   }
-
-  phone_state = PS_ACCEPTED;
-  set_incoming_call_state(sel_caller,CT_active);
-
-  for (cl = cl_head; cl; cl = cl->next)
-  {
-    /* FIXME: this may not be unique enough to identify the right item!
-     * Why not store CallList items in treeview instead of just callers?
-     */
-    if (cl->caller == sel_caller)
-      break;
-  }
-  GNUNET_CONVERSATION_caller_pick_up (sel_caller,
-                                      &caller_event_handler, cl,
-                                      speaker, mic);
-  GCG_HISTORY_add (GCG_HISTORY_TYPE_ACCEPTED, peer_name);
+  GNUNET_break (0);
 }
 
 
 /**
- * Suspending a call
+ * The "suspend" button was clicked.  Pause a call.
+ *
+ * @param button the button
+ * @param user_data builder (unused)
  */
-static void
-do_suspend ()
+void
+GNUNET_CONVERSATION_GTK_on_pause_clicked (GtkButton *button,
+                                          gpointer user_data)
 {
-  if ( (NULL != call_selected) &&
-       (NULL != caller_selected) )
+  if ( (NULL != active_in) &&
+       (NULL != active_out) )
   {
     GNUNET_break(0);
     return;
   }
-  if (NULL != call_selected)
+  if (NULL != active_out)
   {
     /* outgoing */
-    GNUNET_CONVERSATION_call_suspend (call_selected);
-    set_outgoing_call_state(call_selected,CT_suspended);
+    GNUNET_CONVERSATION_call_suspend (active_out->call);
+    set_outgoing_call_state (active_out,
+                             OUT_STATE_SUSPENDED);
+    active_out = NULL;
+    gtk_widget_hide (b_suspend);
+    gtk_widget_hide (b_hangup);
+    gtk_widget_show (b_call);
+    gtk_widget_set_sensitive (b_hangup, FALSE);
+    gtk_widget_set_sensitive (b_suspend, FALSE);
+    gtk_widget_set_sensitive (GTK_WIDGET (address_entry), TRUE);
+    check_call_sensitivity ();
+    do_status ();
+    // FIXME: logging
     return;
   }
-  if (NULL != caller_selected)
+  if (NULL != active_in)
   {
     /* incoming */
-    GNUNET_CONVERSATION_caller_suspend (caller_selected);
-    set_incoming_call_state(caller_selected,CT_suspended);
+    GNUNET_CONVERSATION_caller_suspend (active_in->caller);
+    set_incoming_call_state (active_in,
+                             IN_STATE_SUSPENDED);
+    active_in = NULL;
     phone_state = PS_LISTEN;
+    // FIXME: visibility
+    // FIXME: logging
     return;
   }
   GNUNET_break (0);
@@ -1102,185 +774,296 @@
 
 
 /**
- * Resuming a call
+ * The "hangup" button was clicked.  Hang up.
  *
- * @param args arguments given to the command
+ * @param button the button
+ * @param user_data builder (unused)
  */
-static void
-do_resume ()
+void
+GNUNET_CONVERSATION_GTK_on_hangup_clicked (GtkButton *button,
+                                           gpointer user_data)
 {
-  switch (phone_state)
+  if ( (NULL == active_in) &&
+       (NULL == active_out) )
   {
-  case PS_LOOKUP_EGO:
-  case PS_ERROR:
-    GCG_log ("%s",
-             _("There is no call that could be resumed right now.(PS_ERROR)"));
-    return;
-  case PS_LISTEN:
-    break;
-  case PS_ACCEPTED:
-    GCG_log (_("Already talking with `%s', cannot resume a call right now."),
-             peer_name);
-    return;
-  }
-  if ( (NULL != call_selected) &&
-       (NULL != caller_selected) )
-  {
     GNUNET_break(0);
     return;
   }
-  if (NULL != call_selected)
+  if (NULL != active_out)
   {
-    /* outgoing */
-    GNUNET_CONVERSATION_call_resume (call_selected, speaker, mic);
-    set_outgoing_call_state(call_selected,CT_active);
+    /* if current call is outgoing, stop it */
+    set_outgoing_call_state (active_out,
+                             OUT_STATE_NONE);
+    // FIXME: rather: remove call state!
+    GNUNET_CONVERSATION_call_stop (active_out->call);
+    active_out = NULL;
+    // FIXME: logging
+    gtk_widget_hide (b_suspend);
+    gtk_widget_hide (b_hangup);
+    gtk_widget_show (b_call);
+    gtk_widget_set_sensitive (b_hangup, FALSE);
+    gtk_widget_set_sensitive (b_suspend, FALSE);
+    gtk_widget_set_sensitive (GTK_WIDGET (address_entry), TRUE);
+    check_call_sensitivity ();
+    do_status ();
     return;
   }
-  if (NULL != caller_selected)
+  if (NULL != active_in)
   {
-    /* incoming */
-    GNUNET_CONVERSATION_caller_resume (caller_selected, speaker, mic);
-    set_incoming_call_state(caller_selected,CT_active);
-    phone_state = PS_ACCEPTED;
+    /* if selected call is incoming, hang it up */
+    set_incoming_call_state (active_in,
+                             IN_STATE_NONE);
+    // FIXME: rather: remove call state!
+    GNUNET_CONVERSATION_caller_hang_up (active_in->caller);
+    phone_state = PS_LISTEN;
+    active_in = NULL;
+    // FIXME: logging
+    // FIXME: visibility
     return;
   }
-  GNUNET_break(0);
+  GNUNET_break (0);
 }
 
 
 /**
- / Rejecting a call
+ * Function called with an event emitted by a call.
  *
- * @param args arguments given to the command
+ * @param cls our `struct OutgoingCall`
+ * @param code type of the event on the call
  */
 static void
-do_reject ()
+call_event_handler (void *cls,
+                    enum GNUNET_CONVERSATION_CallEventCode code)
 {
-  if ( (NULL == call_selected) &&
-       (NULL == caller_selected) )
+  struct OutgoingCall *oc = cls;
+
+  set_outgoing_call_state (oc, code);
+  switch (code)
   {
-    GNUNET_break(0);
-    return;
+  case GNUNET_CONVERSATION_EC_CALL_RINGING:
+    GNUNET_break (OUT_STATE_RESOLVING == oc->state);
+    GCG_log (_("Resolved address of `%s'. Now ringing other party."),
+             oc->peer_name);
+    // FIXME: use oc->rr here!
+    set_outgoing_call_state (oc, OUT_STATE_RINGING);
+    GCG_log (_("Ringing `%s'.\n"),
+             oc->peer_name);
+    GCG_update_status_bar (_("Ringing `%s'."),
+                           oc->peer_name);
+    GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-ringing");
+    break;
+  case GNUNET_CONVERSATION_EC_CALL_PICKED_UP:
+    GNUNET_break (OUT_STATE_RINGING == oc->state);
+    set_outgoing_call_state (oc, OUT_STATE_ACTIVE);
+    gtk_widget_set_sensitive (b_suspend, TRUE);
+    GCG_log (_("Connection established to `%s'."),
+             oc->peer_name);
+    GCG_update_status_bar (_("Talking to `%s'."),
+                           oc->peer_name);
+    GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-active");
+    break;
+  case GNUNET_CONVERSATION_EC_CALL_GNS_FAIL:
+    GNUNET_break (OUT_STATE_RESOLVING == oc->state);
+    set_outgoing_call_state (oc, OUT_STATE_NONE);
+    // FIXME: rather: remove from list!
+    GCG_log (_("Failed to resolve %s in current zone."),
+             oc->peer_name);
+    GNUNET_free (oc);
+    active_out = NULL;
+    gtk_widget_hide (b_suspend);
+    gtk_widget_hide (b_hangup);
+    gtk_widget_show (b_call);
+    gtk_widget_set_sensitive (b_hangup, FALSE);
+    gtk_widget_set_sensitive (GTK_WIDGET (address_entry), TRUE);
+    check_call_sensitivity ();
+    do_status ();
+    break;
+  case GNUNET_CONVERSATION_EC_CALL_HUNG_UP:
+    GCG_log ("%s", _("Call terminated"));
+    set_outgoing_call_state (oc, OUT_STATE_NONE);
+    // FIXME: rather: remove from list!
+    GNUNET_free (oc);
+    active_out = NULL;
+    gtk_widget_hide (b_suspend);
+    gtk_widget_hide (b_hangup);
+    gtk_widget_show (b_call);
+    gtk_widget_set_sensitive (b_hangup, FALSE);
+    gtk_widget_set_sensitive (b_suspend, FALSE);
+    gtk_widget_set_sensitive (GTK_WIDGET (address_entry), TRUE);
+    check_call_sensitivity ();
+    do_status ();
+    break;
+  case GNUNET_CONVERSATION_EC_CALL_SUSPENDED:
+    GNUNET_break (OUT_STATE_ACTIVE == oc->state);
+    set_outgoing_call_state (oc, OUT_STATE_SUSPENDED);
+    GCG_log (_("Connection to `%s' suspended (by other user)\n"),
+             oc->peer_name);
+    active_out = NULL;
+    gtk_widget_hide (b_suspend);
+    gtk_widget_hide (b_hangup);
+    gtk_widget_show (b_call);
+    gtk_widget_set_sensitive (b_hangup, FALSE);
+    gtk_widget_set_sensitive (b_suspend, FALSE);
+    gtk_widget_set_sensitive (GTK_WIDGET (address_entry), TRUE);
+    check_call_sensitivity ();
+    do_status ();
+   break;
+  case GNUNET_CONVERSATION_EC_CALL_RESUMED:
+    GNUNET_break (OUT_STATE_ACTIVE == oc->state);
+    GCG_log (_("Connection to `%s' resumed\n"),
+             oc->peer_name);
+    GCG_update_status_bar (_("Talking to `%s'."),
+                           oc->peer_name);
+    GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-active");
+    active_out = oc;
+    set_outgoing_call_state (oc, OUT_STATE_ACTIVE);
+    gtk_widget_show (b_suspend);
+    gtk_widget_show (b_hangup);
+    gtk_widget_hide (b_call);
+    gtk_widget_set_sensitive (b_hangup, TRUE);
+    gtk_widget_set_sensitive (b_suspend, TRUE);
+    gtk_widget_set_sensitive (GTK_WIDGET (address_entry), FALSE);
+    break;
+  case GNUNET_CONVERSATION_EC_CALL_ERROR:
+    GCG_log ("GNUNET_CONVERSATION_EC_CALL_ERROR %s",
+             oc->peer_name);
+    set_outgoing_call_state (oc, OUT_STATE_NONE);
+    // FIXME: rather: remove from list!
+    active_out = NULL;
+    gtk_widget_hide (b_suspend);
+    gtk_widget_hide (b_hangup);
+    gtk_widget_show (b_call);
+    gtk_widget_set_sensitive (b_hangup, FALSE);
+    gtk_widget_set_sensitive (b_suspend, FALSE);
+    gtk_widget_set_sensitive (GTK_WIDGET (address_entry), TRUE);
+    check_call_sensitivity ();
+    do_status ();
+    break;
   }
-  if (NULL != call_selected)
-  {
-    /* if selected call is outgoing, stop it */
-    set_outgoing_call_state (call_selected, CT_hangup);
-    GNUNET_CONVERSATION_call_stop (call);
-    call = NULL;
-    call_selected = NULL;
-    return;
-  }
-  if (NULL != caller_selected)
-  {
-    /* if selected call is incoming, hang it up */
-    set_incoming_call_state (caller_selected,CT_hangup);
-    GNUNET_CONVERSATION_caller_hang_up (caller_selected);
-    phone_state = PS_LISTEN;
-    caller_selected = NULL;
-    return;
-  }
-  GNUNET_break (0);
 }
 
 
 /**
- *  hangup clicked
+ * Initiate a new call.
+ *
+ * @param arg address of the user to call
  */
 void
-GNUNET_CONVERSATION_GTK_on_hangup_clicked ()
+GSC_PHONE_make_call (const char *arg)
 {
-  do_reject ();
-  do_status ();
-}
+  struct GNUNET_IDENTITY_Ego *caller_id;
+  GtkTreeIter gtkiter;
+  struct OutgoingCall *oc;
 
-
-/**
- *  accept clicked
- */
-void
-GNUNET_CONVERSATION_GTK_on_accept_clicked ()
-{
-  if (NULL != caller_selected)
+  gtk_entry_set_text (address_entry,
+                      arg);
+  caller_id = GCG_EGOS_get_selected_ego ();
+  if (NULL == caller_id)
   {
-    do_accept (caller_selected);
+    /* can happen if user activated address in phone book
+       while our phone was still down (no ego selected) */
+    GCG_log (_("Caller ID unavailable, cannot initiate call to `%s'.\n"),
+             arg);
+    return;
   }
-  else
+  if (NULL != active_out)
   {
-    GNUNET_break(0);
+    if (0 == strcmp (active_out->peer_name,
+                     arg))
+      return; /* user likely simply clicked a bit too often, ignore */
+    GCG_log (_("You are on the phone with `%s', suspend or hang up before 
trying to call `%s'!\n"),
+             active_out->peer_name,
+             arg);
+    return;
   }
-  do_status ();
+  switch (phone_state)
+  {
+  case PS_LOOKUP_EGO:
+    GCG_log ("%s\n",
+             _("Caller ID unavailable, cannot initiate call."));
+    return;
+  case PS_LISTEN:
+    /* ok to call! */
+    break;
+  case PS_ACCEPTED:
+    /* `call` should be non-NULL */
+    GNUNET_break (0);
+    return;
+  case PS_ERROR:
+    /* ok to call, we got an ego just could not init the phone */
+    break;
+  }
+  call_counter++;
+  oc = GNUNET_new (struct OutgoingCall);
+  oc->peer_name = GNUNET_strdup (arg);
+  oc->state = OUT_STATE_RESOLVING;
+  oc->call =
+    GNUNET_CONVERSATION_call_start (GCG_get_configuration (),
+                                    caller_id,
+                                    arg,
+                                    speaker, mic,
+                                    &call_event_handler, oc);
+  gtk_list_store_insert_with_values (active_liststore,
+                                     &gtkiter,
+                                     -1,
+                                     GCG_PHONE_LS_CALLER_ID, oc->peer_name,
+                                     GCG_PHONE_LS_CALLER, NULL,
+                                     GCG_PHONE_LS_CALLER_NUM, 0,
+                                     GCG_PHONE_LS_CALLER_STATE, IN_STATE_NONE,
+                                     GCG_PHONE_LS_TYPE, CALL_OUT,
+                                     GCG_PHONE_LS_CALL, oc,
+                                     GCG_PHONE_LS_CALL_NUM, call_counter,
+                                     GCG_PHONE_LS_CALL_STATE, 
OUT_STATE_RESOLVING,
+                                     -1);
+  /* log event */
+  GCG_log (_("Resolving `%s'.\n"),
+           oc->peer_name);
+  GCG_update_status_bar (_("Resolving `%s'."),
+                         oc->peer_name);
+  GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-pending");
+  GCG_HISTORY_add (GCG_HISTORY_TYPE_OUTGOING,
+                   oc->peer_name);
+  /* hide "call" button, make address entry insensitive;
+     show suspend button (but not sensitive),
+     show hangup button (and make sensitive) */
+  gtk_widget_hide (b_call);
+  gtk_widget_set_sensitive (GTK_WIDGET (address_entry), FALSE);
+  gtk_widget_show (b_suspend);
+  gtk_widget_show (b_hangup);
+  gtk_widget_set_sensitive (b_hangup, TRUE);
 }
 
 
 /**
- *  reject clicked
+ * The "connect" button was clicked.  Initiate a call!
+ *
+ * @param button the button
+ * @param user_data builder (unused)
  */
 void
-GNUNET_CONVERSATION_GTK_on_reject_clicked ()
+gnunet_conversation_gtk_call_button_clicked_cb (GtkButton *button,
+                                                gpointer user_data)
 {
-  do_reject ();
-  do_status ();
+  GSC_PHONE_make_call (gtk_entry_get_text (address_entry));
 }
 
 
 /**
- * User clicked the '> contact' button to move the selected
- * caller's information into our address book.
+ * The user has changed the address entry.  Consider activating the
+ * "call" button.
+ *
+ * @param editable entry that was changed
+ * @param user_data builder (unused)
  */
 void
-GNUNET_CONVERSATION_GTK_use_current_button_clicked (GtkButton *button,
-                                                    gpointer *user_data)
+gnunet_conversation_gtk_address_entry_changed_cb (GtkEditable *editable,
+                                                  gpointer user_data)
 {
-  // FIXME: implement, use "GSC_add_contact"
-#if 0
-  GtkEntry *addressEntry;
-
-  addressEntry = GTK_ENTRY (GCG_get_main_window_object 
("GNUNET_GTK_conversation_addressAdd"));
-  gtk_entry_set_text (addressEntry,
-                      "FIXME");
-#endif
+  check_call_sensitivity ();
 }
 
 
 /**
- * pause clicked
- */
-void
-GNUNET_CONVERSATION_GTK_on_pause_clicked ()
-{
-  do_suspend ();
-  do_status ();
-}
-
-/**
- *  resume clicked
- */
-void
-GNUNET_CONVERSATION_GTK_on_resume_clicked ()
-{
-  do_resume ();
-  do_status ();
-}
-
-
-/**
- * call clicked
- */
-void
-GNUNET_CONVERSATION_GTK_on_call_clicked ()
-{
-  GtkEntry *address_entry;
-
-  address_entry = GTK_ENTRY (GCG_get_main_window_object
-                             ("GNUNET_GTK_conversation_address"));
-
-  GSC_PHONE_make_call (gtk_entry_get_text (address_entry));
-  do_status ();
-}
-
-
-/**
  * @brief outgoing ego selector changed, (re)start the phone.
  *
  * @param widget the combo box that changed
@@ -1290,12 +1073,50 @@
 gnunet_conversation_gtk_ego_combobox_changed_cb (GtkComboBox *widget,
                                                  gpointer user_data)
 {
+  struct GNUNET_GNSRECORD_Data rd;
+  struct GNUNET_IDENTITY_Ego *caller_id;
+
   if (NULL != phone)
   {
     GNUNET_CONVERSATION_phone_destroy (phone);
     phone = NULL;
   }
-  start_phone();
+  caller_id = GCG_EGOS_get_selected_ego ();
+  if (NULL == caller_id)
+  {
+    GCG_update_status_bar ("%s",
+                           _("No ego selected, phone is now down."));
+    GCG_log ("%s\n",
+             _("No ego selected, phone is now down."));
+    GCG_set_status_icon ("gnunet-conversation-gtk-tray-pending");
+    phone_state = PS_LOOKUP_EGO;
+    check_call_sensitivity ();
+    return;
+  }
+  phone =
+    GNUNET_CONVERSATION_phone_create (GCG_get_configuration (),
+                                      caller_id,
+                                      &phone_event_handler,
+                                      NULL);
+  if (NULL == phone)
+  {
+    GCG_update_status_bar ("%s",
+                           _("Failed to setup phone (internal error)\n"));
+    GCG_log ("%s",
+             _("Failed to setup phone (internal error)\n"));
+    GCG_set_status_icon ("gnunet-conversation-offline");
+    phone_state = PS_ERROR;
+    check_call_sensitivity ();
+    return;
+  }
+  GNUNET_CONVERSATION_phone_get_record (phone,
+                                        &rd);
+  /* FIXME: publish record to GNS! */
+  GCG_log ("%s\n",
+           _("Phone active"));
+  phone_state = PS_LISTEN;
+  check_call_sensitivity ();
+  do_status();
 }
 
 
@@ -1310,7 +1131,7 @@
   cfg = GCG_get_configuration ();
   speaker = GNUNET_SPEAKER_create_from_hardware (cfg);
   mic = GNUNET_MICROPHONE_create_from_hardware (cfg);
-  /* get gui objects */
+
   b_add_contact = GTK_WIDGET (GCG_get_main_window_object
                               ("gnunet_conversation_gtk_add_contact_button"));
   b_accept  = GTK_WIDGET (GCG_get_main_window_object
@@ -1325,7 +1146,8 @@
                           ("gnunet_conversation_gtk_call_button"));
   b_hangup = GTK_WIDGET (GCG_get_main_window_object
                          ("gnunet_conversation_gtk_hangup_button"));
-
+  address_entry = GTK_ENTRY (GCG_get_main_window_object
+                             ("gnunet_conversation_gtk_address_entry"));
   active_liststore =
      GTK_LIST_STORE (GCG_get_main_window_object
                      ("gnunet_conversation_gtk_active_calls_liststore"));
@@ -1341,22 +1163,19 @@
 void
 GCG_PHONE_shutdown ()
 {
-  struct CallList *cl;
-
-  while (NULL != (cl = cl_head))
+  if (NULL != active_in)
   {
-    GNUNET_CONVERSATION_caller_hang_up (cl->caller);
-    GNUNET_CONTAINER_DLL_remove (cl_head,
-                                 cl_tail,
-                                 cl);
-    // FIXME: release other memory?
-    GNUNET_free (cl);
+    GNUNET_CONVERSATION_caller_hang_up (active_in->caller);
+    // FIXME: memory leak
+    active_in = NULL;
   }
-  if (NULL != call)
+  if (NULL != active_out)
   {
-    GNUNET_CONVERSATION_call_stop (call);
-    call = NULL;
+    GNUNET_CONVERSATION_call_stop (active_out->call);
+    // FIXME: memory leak
+    active_out = NULL;
   }
+  // FIXME: clean up tree view!
   if (NULL != phone)
   {
     GNUNET_CONVERSATION_phone_destroy (phone);
@@ -1366,8 +1185,6 @@
   speaker = NULL;
   GNUNET_MICROPHONE_destroy (mic);
   mic = NULL;
-  GNUNET_free_non_null (peer_name);
-  peer_name = NULL;
   phone_state = PS_ERROR;
 }
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]