aboutsummaryrefslogtreecommitdiff
path: root/src/conversation/gnunet-conversation-gtk_phone.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/conversation/gnunet-conversation-gtk_phone.c')
-rw-r--r--src/conversation/gnunet-conversation-gtk_phone.c1571
1 files changed, 694 insertions, 877 deletions
diff --git a/src/conversation/gnunet-conversation-gtk_phone.c b/src/conversation/gnunet-conversation-gtk_phone.c
index 05be2bfa..bbd1cb53 100644
--- a/src/conversation/gnunet-conversation-gtk_phone.c
+++ b/src/conversation/gnunet-conversation-gtk_phone.c
@@ -33,42 +33,67 @@
33 33
34 34
35/** 35/**
36 * active calls treeview columns 36 * Active calls treeview columns
37 */ 37 */
38enum ActiveCallsTreeViewColumns 38enum ActiveCallsTreeViewColumns
39{ 39{
40 AL_caller_id, //*gchar 40 /**
41 AL_caller, //* 41 * A `gchar *`
42 AL_caller_num, //gint 42 */
43 AL_type, //gint 43 GCG_PHONE_LS_CALLER_ID,
44 AL_caller_state, //gint
45 AL_call, //*
46 AL_call_state, //gint
47 AL_call_num //gint
48};
49 44
45 /**
46 * A `struct IncomingCall *`
47 */
48 GCG_PHONE_LS_CALLER,
49
50 /**
51 * A `gint`.
52 */
53 GCG_PHONE_LS_CALLER_NUM,
54
55 /**
56 * A `gint` for a `enum TypeOfConversation` (FIXME: remove?)
57 */
58 GCG_PHONE_LS_TYPE,
59
60 /**
61 * A `gint` for a `enum InCallState` (FIXME: replace with char *!)
62 */
63 GCG_PHONE_LS_CALLER_STATE,
64
65 /**
66 * A `struct OutgoingCall *`.
67 */
68 GCG_PHONE_LS_CALL,
69
70 /**
71 * A `gint` for a `enum OutCallState` (FIXME: replace with char *,
72 * combine with #GCG_PHONE_LS_CALLER_STATE).
73 */
74 GCG_PHONE_LS_CALL_STATE,
75
76 /**
77 * A `gint`. FIXME: combine with #GCG_PHONE_LS_CALLER_NUM!
78 */
79 GCG_PHONE_LS_CALL_NUM
50 80
51/**
52 * callerstate (state of incoming call)
53 */
54enum CallerState
55{
56 CT_active,
57 CT_suspended,
58 CT_ringing,
59 CT_dead,
60 CT_hangup,
61 CT_rejected,
62 CT_other
63}; 81};
64 82
65 83
66/** 84/**
67 * type of call 85 * Types of conversations
68 */ 86 */
69enum TypeOfCall 87enum TypeOfConversation
70{ 88{
89 /**
90 * Incoming phone call.
91 */
71 CALL_IN, 92 CALL_IN,
93
94 /**
95 * Outgoing call.
96 */
72 CALL_OUT 97 CALL_OUT
73}; 98};
74 99
@@ -79,7 +104,7 @@ enum TypeOfCall
79enum PhoneState 104enum PhoneState
80{ 105{
81 /** 106 /**
82 * We're waiting for our own idenitty. 107 * We're waiting for the user to select a caller ID.
83 */ 108 */
84 PS_LOOKUP_EGO, 109 PS_LOOKUP_EGO,
85 110
@@ -101,58 +126,75 @@ enum PhoneState
101 126
102 127
103/** 128/**
104 * States for current outgoing call. 129 * States for current incoming call.
105 */ 130 */
106enum CallState 131enum InCallState
107{ 132{
108 /** 133 /**
109 * We are looking up some other participant. 134 * No incoming call.
110 */ 135 */
111 CS_RESOLVING, 136 IN_STATE_NONE,
112 137
113 /** 138 /**
114 * We are now ringing the other participant. 139 * Our phone is ringing.
115 */ 140 */
116 CS_RINGING, 141 IN_STATE_RINGING,
117 142
118 /** 143 /**
119 * The other party accepted our call and we are now connected. 144 * The other party accepted our call and we are now connected.
120 */ 145 */
121 CS_CONNECTED, 146 IN_STATE_CONNECTED,
122 147
123 /** 148 /**
124 * The call is currently suspended (by us). 149 * The call is currently suspended (by us).
125 */ 150 */
126 CS_SUSPENDED 151 IN_STATE_SUSPENDED
127}; 152};
128 153
129 154
130
131/** 155/**
132 * List of incoming calls 156 * Possible states of outgoing phone calls.
133 */ 157 */
134struct CallList 158enum OutCallState
135{ 159{
160 /**
161 * Phone state we use if this is not an outgoing call.
162 */
163 OUT_STATE_NONE,
136 164
137 /** 165 /**
138 * A DLL. 166 * This phone call is currently resolving.
139 */ 167 */
140 struct CallList *prev; 168 OUT_STATE_RESOLVING,
141 169
142 /** 170 /**
143 * A DLL. 171 * This phone call is currently ringing.
144 */ 172 */
145 struct CallList *next; 173 OUT_STATE_RINGING,
146 174
147 /** 175 /**
148 * Handle to hang up or activate. 176 * This phone call is currently active.
149 */ 177 */
150 struct GNUNET_CONVERSATION_Caller *caller; 178 OUT_STATE_ACTIVE,
151 179
152 /** 180 /**
153 * Handle to call currently selected in list 181 * This phone call is currently suspended.
154 */ 182 */
155 struct GNUNET_CONVERSATION_Caller *caller_selected; 183 OUT_STATE_SUSPENDED
184
185};
186
187
188/**
189 * List of incoming calls
190 */
191struct IncomingCall
192{
193
194 /**
195 * Handle to hang up or activate.
196 */
197 struct GNUNET_CONVERSATION_Caller *caller;
156 198
157 /** 199 /**
158 * String identifying the caller. 200 * String identifying the caller.
@@ -160,22 +202,55 @@ struct CallList
160 char *caller_id; 202 char *caller_id;
161 203
162 /** 204 /**
205 * Location of this call in the list.
206 */
207 GtkTreeRowReference *rr;
208
209 /**
163 * Unique number of the caller. 210 * Unique number of the caller.
164 */ 211 */
165 unsigned int caller_num; 212 unsigned int caller_num;
166 213
214 /**
215 * State for this call.
216 */
217 enum InCallState state;
218
167}; 219};
168 220
169 221
170/** 222/**
171 * 223 * Information we keep for an outgoing call.
172 */ 224 */
173static struct GNUNET_CONVERSATION_Caller *caller_selected; 225struct OutgoingCall
226{
174 227
175/** 228 /**
176 * 229 * Associated conversation handle.
177 */ 230 */
178static struct GNUNET_CONVERSATION_Call *call_selected; 231 struct GNUNET_CONVERSATION_Call *call;
232
233 /**
234 * Name of conversation partner.
235 */
236 char *peer_name;
237
238 /**
239 * Location of this call in the list.
240 */
241 GtkTreeRowReference *rr;
242
243 /**
244 * Unique number of the caller.
245 */
246 unsigned int caller_num;
247
248 /**
249 * State for this call.
250 */
251 enum OutCallState state;
252
253};
179 254
180 255
181/** 256/**
@@ -189,84 +264,91 @@ static GtkListStore *active_liststore;
189static GtkTreeView *active_treeview; 264static GtkTreeView *active_treeview;
190 265
191/** 266/**
192 * Unique number of call (outgoing)
193 */
194static unsigned int call_counter;
195
196/**
197 * Counts the number of incoming calls we have had so far.
198 */
199static unsigned int caller_num_gen;
200
201/**
202 * Phone handle 267 * Phone handle
203 */ 268 */
204static struct GNUNET_CONVERSATION_Phone *phone; 269static struct GNUNET_CONVERSATION_Phone *phone;
205 270
206/** 271/**
207 * Call handle (for active outgoing call). 272 * Our speaker.
208 */ 273 */
209static struct GNUNET_CONVERSATION_Call *call; 274static struct GNUNET_SPEAKER_Handle *speaker;
210 275
211/** 276/**
212 * Caller handle (for active incoming call). 277 * Our microphone.
213 */ 278 */
214static struct CallList *cl_active; 279static struct GNUNET_MICROPHONE_Handle *mic;
215 280
216/** 281/**
217 * Head of calls waiting to be accepted. 282 * Our phone's current state.
218 */ 283 */
219static struct CallList *cl_head; 284static enum PhoneState phone_state;
220 285
221/**
222 * Tail of calls waiting to be accepted.
223 */
224static struct CallList *cl_tail;
225 286
226/** 287/**
227 * Our speaker. 288 * Counts the number of incoming calls we have had so far.
228 */ 289 */
229static struct GNUNET_SPEAKER_Handle *speaker; 290static unsigned int caller_num_gen;
230 291
231/** 292/**
232 * Our microphone. 293 * Unique number of call (outgoing)
233 */ 294 */
234static struct GNUNET_MICROPHONE_Handle *mic; 295static unsigned int call_counter;
235 296
236/** 297/**
237 * Our phone's current state. 298 * Number of incoming calls that are currently ringing.
238 */ 299 */
239static enum PhoneState phone_state; 300static unsigned int in_ring_counter;
240 301
241/** 302/**
242 * Our call's current state. 303 * Caller handle (for active incoming call, or NULL).
243 */ 304 */
244static enum CallState call_state; 305static struct IncomingCall *active_in;
245 306
246/** 307/**
247 * Name of conversation partner (if any). 308 * Call handle (of the active outgoing call, or NULL).
248 */ 309 */
249static char *peer_name; 310static struct OutgoingCall *active_out;
311
250 312
251/** 313/**
252 * GNS address for this phone. 314 * The "add contact" (or "> contact") button.
253 */ 315 */
254static char *address;
255
256static GtkWidget *b_add_contact; 316static GtkWidget *b_add_contact;
257 317
318/**
319 * The "accept" button.
320 */
258static GtkWidget *b_accept; 321static GtkWidget *b_accept;
259 322
323/**
324 * The "refuse" button.
325 */
260static GtkWidget *b_refuse; 326static GtkWidget *b_refuse;
261 327
262static GtkWidget *b_suspend; // pause 328/**
329 * The "pause" button.
330 */
331static GtkWidget *b_suspend;
263 332
333/**
334 * The "resume" button.
335 */
264static GtkWidget *b_resume; 336static GtkWidget *b_resume;
265 337
266static GtkWidget *b_call; // connect 338/**
339 * The "connect" button.
340 */
341static GtkWidget *b_call;
267 342
268static GtkWidget *b_hangup; // disconnect up 343/**
344 * The "disconnect" button.
345 */
346static GtkWidget *b_hangup;
269 347
348/**
349 * Our address entry.
350 */
351static GtkEntry *address_entry;
270 352
271 353
272/** 354/**
@@ -277,249 +359,41 @@ static GtkWidget *b_hangup; // disconnect up
277static void 359static void
278do_status () 360do_status ()
279{ 361{
280 switch (phone_state) 362 if ( (NULL == active_in) &&
363 (NULL == active_out) &&
364 (0 != in_ring_counter) )
281 { 365 {
282 case PS_LOOKUP_EGO: 366 GCG_update_status_bar (_("The phone is ringing (%u calls waiting)"),
283 GCG_update_status_bar ("%s", 367 in_ring_counter);
284 _("Phone inactive: no ego selected for the caller ID.")); 368 GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-incoming");
285 GCG_set_status_icon ("gnunet-conversation-gtk-tray-pending"); 369 return;
286 break;
287 case PS_LISTEN:
288 GCG_update_status_bar ("%s",
289 _("We are listening for incoming calls"));
290 GCG_set_status_icon ("gnunet-conversation-gtk-tray-available");
291 break;
292 case PS_ACCEPTED:
293 GCG_update_status_bar (_("You are having a conversation with `%s'.\n"),
294 peer_name);
295 GCG_set_status_icon ("gnunet-conversation-call-active");
296 break;
297 case PS_ERROR:
298 GCG_update_status_bar (_("We had an internal error setting up our phone line. You can still make calls."));
299 GCG_set_status_icon ("gnunet-conversation-offline");
300 break;
301 } 370 }
302 if (NULL != call) 371 if ( (NULL == active_in) &&
372 (NULL == active_out) &&
373 (PS_LISTEN == phone_state) )
303 { 374 {
304 switch (call_state) 375 GCG_update_status_bar ("%s",
305 { 376 _("We are listening for incoming calls"));
306 case CS_RESOLVING: 377 GCG_set_status_icon ("gnunet-conversation-gtk-tray-available");
307 GCG_update_status_bar (_("We are trying to find the network address to call `%s'."),
308 peer_name);
309 GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-pending");
310 break;
311 case CS_RINGING:
312 GCG_update_status_bar (_("We are calling `%s', his phone should be ringing."),
313 peer_name);
314 GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-ringing");
315 break;
316 case CS_CONNECTED:
317 GCG_update_status_bar (_("You are having a conversation with `%s'."),
318 peer_name);
319 GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-active");
320 break;
321 case CS_SUSPENDED:
322 GCG_update_status_bar (_("Conversation suspended, you can accept or initiate another call now."),
323 peer_name);
324 GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-suspended");
325 break;
326 }
327 } 378 }
328 if ( ( (NULL == call) ||
329 (CS_SUSPENDED == call_state) ) &&
330 (NULL != cl_head) &&
331 ( (cl_head != cl_active) ||
332 (cl_head != cl_tail) ) )
333 GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-incoming");
334} 379}
335 380
336 381
337
338/** 382/**
339 * @brief print info for currently selected call 383 * Check if the conditions are met for the "call" button to
384 * be sensitive again. Those conditions are that we must
385 * have a phone that is ready to "listen" (no error or active
386 * call), and that some address text is in the address entry.
340 */ 387 */
341static void 388static void
342print_call_info () 389check_call_sensitivity ()
343{ 390{
344 GtkTreeIter gtkiter; 391 gboolean sens;
345 gboolean valid;
346 gint row_count = 0;
347 392
348 valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (active_liststore), 393 sens = (PS_LISTEN == phone_state);
349 &gtkiter); 394 if (0 == strlen (gtk_entry_get_text (address_entry)))
350 if (! valid) 395 sens = FALSE;
351 GNUNET_break(0); 396 gtk_widget_set_sensitive (b_call, sens);
352
353 while (valid)
354 {
355 gchar *str_data;
356 gint int_data;
357 gpointer cl_caller;
358 gpointer cl_call;
359
360 gtk_tree_model_get (GTK_TREE_MODEL (active_liststore),
361 &gtkiter,
362 AL_caller, &cl_caller,
363 AL_caller_id, &str_data,
364 AL_caller_num, &int_data,
365 AL_call, &cl_call,
366 -1);
367 if (call_selected == cl_call)
368 {
369 GCG_log (_("info for active outgoing call:%s number: %u row: %u"),
370 str_data,
371 int_data,
372 row_count);
373 break;
374 }
375 g_free (str_data);
376 row_count++;
377 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(active_liststore), &gtkiter);
378 }
379}
380
381
382/**
383 * @brief sets caller_selected, and enables or disables the active call list buttons
384 */
385static void
386update_active_call_list_buttons ()
387{
388 gchar *caller_id;
389 gpointer cl_caller;
390 gpointer cl_call;
391 gint cl_caller_state;
392 gint cl_type;
393 //gint cl_caller_type;
394 GtkTreeSelection *active_selection;
395 GtkTreeIter gcl_selected;
396 // active_liststore_selection = GCG_get_main_window_object(ml,"GNUNET_CONVERSATION_GTK_active_calls_selection");
397
398 // reset references to selected call/caller
399 //caller_selected = NULL;
400 //call_selected = NULL;
401 GCG_log("reset caller selected");
402 active_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (active_treeview));
403 if (gtk_tree_selection_get_selected (active_selection,
404 NULL,
405 &gcl_selected))
406 {
407 // get selected call
408 gtk_tree_model_get (GTK_TREE_MODEL(active_liststore), &gcl_selected,
409 AL_caller, &cl_caller, // reference to incoming call
410 AL_caller_id, &caller_id,
411 AL_caller_state, &cl_caller_state,
412 AL_type, &cl_type,
413 AL_call, &cl_call, // reference to outgoing call
414 -1);
415 // check if selected call is a incoming or outgoing call
416 switch (cl_type)
417 {
418 case CALL_IN:
419 call_selected = NULL;
420 caller_selected = cl_caller;
421 GNUNET_break (NULL != caller_selected);
422 break;
423 case CALL_OUT:
424 caller_selected = NULL;
425 call_selected = cl_call;
426 GCG_log("outgoing selected");
427 GNUNET_break (NULL != call_selected);
428 break;
429 default:
430 GNUNET_break(0);
431 break;
432 }
433 gtk_widget_show(GTK_WIDGET(GCG_get_main_window_object("GNUNET_GTK_conversation_active_call_list_buttons")));
434 GCG_log("caller state: %u phone_state: %u",
435 cl_caller_state,
436 phone_state);
437 switch (cl_caller_state)
438 {
439 /* buttons:
440 * contact
441 * accept
442 * hangup
443 * suspend
444 * resume
445 *
446 * TODO: check if there is incoming or outgoing call,
447 * disable resume and accept buttons.
448 * or suspend that other call
449 */
450 case CT_active:
451 // hangup, pause
452 //GCG_log("CT_active state: %u ",cl_caller_state);
453 gtk_widget_set_sensitive (b_add_contact, TRUE);
454 gtk_widget_set_sensitive (b_accept, FALSE);
455 gtk_widget_set_sensitive (b_hangup, TRUE);
456 gtk_widget_set_sensitive (b_suspend, TRUE);
457 gtk_widget_set_sensitive (b_resume, FALSE);
458 break;
459 case CT_ringing:
460 // pickup, phonebook
461 //GCG_log("CT_ring show button");
462 gtk_widget_set_sensitive (b_add_contact, TRUE);
463 if (phone_state == PS_LISTEN)
464 {
465 gtk_widget_set_sensitive (b_accept, TRUE);
466 }
467 else
468 {
469 gtk_widget_set_sensitive (b_accept, FALSE);
470 }
471 gtk_widget_set_sensitive (b_hangup, FALSE);
472 gtk_widget_set_sensitive (b_suspend, FALSE);
473 gtk_widget_set_sensitive (b_resume, FALSE);
474 break;
475 case CT_rejected:
476 //add to phonebook
477 //GCG_log("CT_rejected ");
478 gtk_widget_set_sensitive (b_add_contact, TRUE);
479 gtk_widget_set_sensitive (b_accept, FALSE);
480 gtk_widget_set_sensitive (b_hangup, FALSE);
481 gtk_widget_set_sensitive (b_suspend, FALSE);
482 gtk_widget_set_sensitive (b_resume, FALSE);
483 break;
484 case CT_suspended:
485 // resume, hangup
486 //GCG_log("CT_suspended ");
487 gtk_widget_set_sensitive (b_add_contact, TRUE);
488 gtk_widget_set_sensitive (b_accept, FALSE);
489 gtk_widget_set_sensitive (b_hangup, TRUE);
490 gtk_widget_set_sensitive (b_suspend, FALSE);
491 if (phone_state == PS_LISTEN)
492 {
493 GCG_log("enable resume button");
494 gtk_widget_set_sensitive (b_resume, TRUE);
495 }
496 else
497 {
498 GCG_log("do not disable resume button (for test)");
499 gtk_widget_set_sensitive (b_resume, TRUE);
500 }
501 break;
502 case CT_other:
503 //add to phonebook
504 //GCG_log("CT_rejected ");
505 gtk_widget_set_sensitive (b_add_contact, TRUE);
506 gtk_widget_set_sensitive (b_accept, TRUE);
507 gtk_widget_set_sensitive (b_hangup, TRUE);
508 gtk_widget_set_sensitive (b_suspend, TRUE);
509 gtk_widget_set_sensitive (b_resume, TRUE);
510 break;
511
512 default:
513 GNUNET_break(0);
514 break;
515 }
516 print_call_info();
517 }
518 else
519 {
520 GCG_log("nothing selected");
521 //gtk_widget_hide(GTK_WIDGET(GCG_get_main_window_object("GNUNET_GTK_conversation_active_call_list_buttons" )));
522 }
523} 397}
524 398
525 399
@@ -529,200 +403,85 @@ update_active_call_list_buttons ()
529void 403void
530gnunet_conversation_gtk_active_calls_treeview_selection_changed_cb () 404gnunet_conversation_gtk_active_calls_treeview_selection_changed_cb ()
531{ 405{
532 update_active_call_list_buttons(); 406 // FIXME
533}
534
535
536static void
537disable_list_buttons ()
538{
539 gtk_widget_set_sensitive (b_add_contact, FALSE);
540 gtk_widget_set_sensitive (b_accept, FALSE);
541 gtk_widget_set_sensitive (b_hangup, FALSE);
542 gtk_widget_set_sensitive (b_suspend, FALSE);
543 gtk_widget_set_sensitive (b_resume, FALSE);
544} 407}
545 408
546 409
547/** 410/**
548 * set state of outgoing call 411 * Set state of outgoing call.
412 *
413 * @param oc outgoing call to change state of
414 * @param state new state of the call
549 */ 415 */
550static void 416static void
551set_outgoing_call_state (struct GNUNET_CONVERSATION_Call *call, 417set_outgoing_call_state (struct OutgoingCall *oc,
552 int state) 418 enum OutCallState state)
553{ 419{
554 GtkTreeIter gtkiter; 420 GtkTreePath *path;
555 gint valid = 0; 421 GtkTreeIter iter;
556 gint cl_type; 422
557 423 path = gtk_tree_row_reference_get_path (oc->rr);
558 valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (active_liststore), 424 GNUNET_assert (gtk_tree_model_get_iter (GTK_TREE_MODEL (active_liststore),
559 &gtkiter); 425 &iter,
560 if (!valid) 426 path));
561 GNUNET_break(0); 427 gtk_tree_path_free (path);
562 while (valid) 428 switch (state)
563 { 429 {
564 gchar *cl_caller_id; 430 case OUT_STATE_NONE:
565 gint cl_caller_num; 431 gtk_list_store_remove (active_liststore,
566 gpointer cl_call; 432 &iter);
567 433 return;
568 gtk_tree_model_get ( GTK_TREE_MODEL( active_liststore ), &gtkiter, 434 case OUT_STATE_RESOLVING:
569 AL_call, &cl_call, 435 break;
570 AL_caller_id,&cl_caller_id, 436 case OUT_STATE_RINGING:
571 AL_caller_num,&cl_caller_num, 437 break;
572 AL_type, &cl_type, 438 case OUT_STATE_ACTIVE:
573 -1); 439 break;
574 if (cl_type == CALL_OUT) 440 case OUT_STATE_SUSPENDED:
575 { 441 break;
576 if (call == NULL) // function called by phone event handler
577 {
578 GCG_log("event handler");
579 gtk_list_store_set(active_liststore, &gtkiter,
580 AL_call_state, state,
581 -1);
582 switch (state)
583 {
584 /**
585 * We are the caller and are now ringing the other party (GNS lookup
586 * succeeded).
587 */
588 case GNUNET_CONVERSATION_EC_CALL_RINGING:
589 break;
590 /**
591 * We are the caller and are now ready to talk as the callee picked up.
592 */
593 case GNUNET_CONVERSATION_EC_CALL_PICKED_UP:
594 break;
595 /**
596 * We are the caller and failed to locate a phone record in GNS.
597 * After this invocation, the respective call handle will be
598 * automatically destroyed and the client must no longer call
599 * #GNUNET_CONVERSATION_call_stop or any other function on the
600 * call object.
601 */
602 case GNUNET_CONVERSATION_EC_CALL_GNS_FAIL:
603 gtk_list_store_remove(active_liststore,&gtkiter);
604 disable_list_buttons();
605 break;
606 /**
607 * We are the caller and the callee called
608 * #GNUNET_CONVERSATION_caller_hang_up. After this invocation, the
609 * respective call handle will be automatically destroyed and the
610 * client must no longer call #GNUNET_CONVERSATION_call_stop.
611 */
612 case GNUNET_CONVERSATION_EC_CALL_HUNG_UP:
613 gtk_list_store_remove(active_liststore,&gtkiter);
614 disable_list_buttons();
615 break;
616 /**
617 * We are the caller and the callee suspended the call. Note that
618 * both sides can independently suspend and resume calls; a call is
619 * only "working" of both sides are active.
620 */
621 case GNUNET_CONVERSATION_EC_CALL_SUSPENDED:
622 break;
623 /**
624 * We are the caller and the callee suspended the call. Note that
625 * both sides can independently suspend and resume calls; a call is
626 * only "working" of both sides are active.
627 */
628 case GNUNET_CONVERSATION_EC_CALL_RESUMED:
629 break;
630 /**
631 * We had an error handing the call, and are now restarting it
632 * (back to lookup). This happens, for example, if the peer
633 * is restarted during a call.
634 */
635 case GNUNET_CONVERSATION_EC_CALL_ERROR:
636 break;
637 default:
638 break;
639 }
640 }
641 else if (call == cl_call) // function called for specific call
642 {
643 //GCG_log (_("setting state for call:%u row: %u state: %u"),cl_caller_num,row_count,state);
644
645 switch (state)
646 {
647 case CT_hangup:
648 //GCG_log("remove line cause hangup");
649 gtk_list_store_remove(active_liststore,&gtkiter);
650 disable_list_buttons();
651 break;
652 case CT_rejected:
653 //GCG_log("remove line cause rejected");
654 gtk_list_store_remove(active_liststore,&gtkiter);
655 disable_list_buttons();
656 break;
657 default:
658 gtk_list_store_set(active_liststore, &gtkiter,
659 AL_caller_state, state,
660 -1);
661 break;
662 }
663 }
664 }
665 g_free (cl_caller_id);
666 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(active_liststore), &gtkiter);
667 } 442 }
668 GCG_update_status_bar (""); 443 gtk_list_store_set (active_liststore,
444 &iter,
445 GCG_PHONE_LS_CALL_STATE, state,
446 -1);
669} 447}
670 448
671 449
672/** 450/**
673 * set call state of a incoming call 451 * Set call state of a incoming call
452 *
453 * @param ic incoming call to change state of
454 * @param state new state of the call
674 */ 455 */
675static void 456static void
676set_incoming_call_state (struct GNUNET_CONVERSATION_Caller *caller, 457set_incoming_call_state (struct IncomingCall *ic,
677 int state) 458 enum InCallState state)
678{ 459{
679 GtkTreeIter gtkiter; 460 GtkTreePath *path;
680 gint valid = 0; 461 GtkTreeIter iter;
681 462
682 valid = gtk_tree_model_get_iter_first( GTK_TREE_MODEL( active_liststore ), &gtkiter ); 463 path = gtk_tree_row_reference_get_path (ic->rr);
683 if (!valid) 464 GNUNET_assert (gtk_tree_model_get_iter (GTK_TREE_MODEL (active_liststore),
684 GNUNET_break(0); 465 &iter,
685 while (valid) 466 path));
467 gtk_tree_path_free (path);
468 switch (state)
686 { 469 {
687 gchar *cl_caller_id; 470 case IN_STATE_NONE:
688 gint cl_caller_num; 471 gtk_list_store_remove (active_liststore,
689 gpointer cl_caller; 472 &iter);
690 473 return;
691 gtk_tree_model_get (GTK_TREE_MODEL (active_liststore ), 474 case IN_STATE_RINGING:
692 &gtkiter, 475 break;
693 AL_caller, &cl_caller, 476 case IN_STATE_CONNECTED:
694 AL_caller_id, &cl_caller_id, 477 break;
695 AL_caller_num, &cl_caller_num, 478 case IN_STATE_SUSPENDED:
696 -1); 479 break;
697 if (caller == cl_caller)
698 {
699 switch (state)
700 {
701 case CT_hangup:
702 //GCG_log("remove line cause hangup");
703 gtk_list_store_remove (active_liststore,
704 &gtkiter);
705 disable_list_buttons ();
706 break;
707 case CT_rejected:
708 //GCG_log("remove line cause rejected");
709 gtk_list_store_remove (active_liststore,
710 &gtkiter);
711 disable_list_buttons ();
712 break;
713 default:
714 gtk_list_store_set (active_liststore,
715 &gtkiter,
716 AL_caller_state, state,
717 -1);
718 break;
719 }
720 }
721 g_free (cl_caller_id);
722 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(active_liststore),
723 &gtkiter);
724 } 480 }
725 GCG_update_status_bar(""); 481 gtk_list_store_set (active_liststore,
482 &iter,
483 GCG_PHONE_LS_CALLER_STATE, state,
484 -1);
726} 485}
727 486
728 487
@@ -740,61 +499,59 @@ phone_event_handler (void *cls,
740 struct GNUNET_CONVERSATION_Caller *caller, 499 struct GNUNET_CONVERSATION_Caller *caller,
741 const char *caller_id) 500 const char *caller_id)
742{ 501{
743 GtkTreeIter gtkiter; 502 GtkTreeIter iter;
744 GtkTreeIter gtkiter1;
745 gboolean valid; 503 gboolean valid;
746 struct CallList *cl; 504 struct IncomingCall *ic;
747 505
748 switch (code) 506 switch (code)
749 { 507 {
750 case GNUNET_CONVERSATION_EC_PHONE_RING: 508 case GNUNET_CONVERSATION_EC_PHONE_RING:
751 caller_num_gen++; 509 ic = GNUNET_new (struct IncomingCall);
510 ic->caller = caller;
511 ic->caller_id = GNUNET_strdup (caller_id);
512 ic->caller_num = caller_num_gen++;
513 gtk_list_store_insert_with_values (active_liststore,
514 &iter,
515 -1,
516 GCG_PHONE_LS_CALLER_ID, caller_id,
517 GCG_PHONE_LS_CALLER, ic,
518 GCG_PHONE_LS_CALLER_NUM, caller_num_gen,
519 GCG_PHONE_LS_CALLER_STATE, IN_STATE_RINGING,
520 GCG_PHONE_LS_TYPE, CALL_IN,
521 -1);
522 // FIXME: initialize ic->rr
752 GCG_log (_("A Incoming call from `%s' with number %u\n"), 523 GCG_log (_("A Incoming call from `%s' with number %u\n"),
753 caller_id, 524 caller_id,
754 caller_num_gen); 525 caller_num_gen);
755 cl = GNUNET_new (struct CallList);
756 cl->caller = caller;
757 cl->caller_id = GNUNET_strdup (caller_id);
758 cl->caller_num = caller_num_gen;
759 GNUNET_CONTAINER_DLL_insert (cl_head, cl_tail, cl);
760 gtk_list_store_append (active_liststore,
761 &gtkiter);
762 gtk_list_store_set (active_liststore,
763 &gtkiter,
764 AL_caller_id, caller_id,
765 AL_caller, caller,
766 AL_caller_num, caller_num_gen,
767 AL_caller_state, CT_ringing,
768 AL_type, CALL_IN,
769 -1);
770 break; 526 break;
771 case GNUNET_CONVERSATION_EC_PHONE_HUNG_UP: 527 case GNUNET_CONVERSATION_EC_PHONE_HUNG_UP:
772 valid = gtk_tree_model_get_iter_first( GTK_TREE_MODEL( active_liststore ), &gtkiter1 ); 528 valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (active_liststore),
773 if (!valid) 529 &iter);
774 GNUNET_break(0); 530 GNUNET_break (valid);
775 while (valid) 531 while (valid)
776 { 532 {
777 gchar *str_data; 533 gchar *str_data;
778 gint int_data; 534 gint int_data;
779 gpointer cl_caller; 535 struct IncomingCall *ic;
780 536
781 gtk_tree_model_get (GTK_TREE_MODEL(active_liststore), 537 gtk_tree_model_get (GTK_TREE_MODEL (active_liststore),
782 &gtkiter1, 538 &iter,
783 AL_caller, &cl_caller, 539 GCG_PHONE_LS_CALLER, &ic,
784 AL_caller_id, &str_data, 540 GCG_PHONE_LS_CALLER_ID, &str_data,
785 AL_caller_num, &int_data, 541 GCG_PHONE_LS_CALLER_NUM, &int_data,
786 -1); 542 -1);
787 if (caller == cl_caller) 543 if (caller == ic->caller)
788 { 544 {
789 GCG_log (_("phone hung up:%s number: %u "), 545 GCG_log (_("phone hung up:%s number: %u "),
790 str_data, 546 str_data,
791 int_data); 547 int_data);
792 set_incoming_call_state (caller, 548 set_incoming_call_state (ic,
793 CT_rejected); 549 IN_STATE_NONE);
794 break; 550 break;
795 } 551 }
796 g_free (str_data); 552 g_free (str_data);
797 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(active_liststore), &gtkiter1); 553 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (active_liststore),
554 &iter);
798 } 555 }
799 phone_state = PS_LISTEN; 556 phone_state = PS_LISTEN;
800 break; 557 break;
@@ -813,7 +570,7 @@ static void
813caller_event_handler (void *cls, 570caller_event_handler (void *cls,
814 enum GNUNET_CONVERSATION_CallerEventCode code) 571 enum GNUNET_CONVERSATION_CallerEventCode code)
815{ 572{
816 struct CallList *cl = cls; 573 struct IncomingCall *cl = cls;
817 574
818 if (NULL == cl) 575 if (NULL == cl)
819 { 576 {
@@ -824,12 +581,16 @@ caller_event_handler (void *cls,
824 { 581 {
825 case GNUNET_CONVERSATION_EC_CALLER_SUSPEND: 582 case GNUNET_CONVERSATION_EC_CALLER_SUSPEND:
826 //TODO: should this be cls? not cl->caller 583 //TODO: should this be cls? not cl->caller
827 set_incoming_call_state(cl->caller,CT_suspended); 584 set_incoming_call_state (cl,
828 GCG_log (_("Call from `%s' suspended by other user\n"), cl->caller_id); 585 IN_STATE_SUSPENDED);
586 GCG_log (_("Call from `%s' suspended by other user\n"),
587 cl->caller_id);
829 break; 588 break;
830 case GNUNET_CONVERSATION_EC_CALLER_RESUME: 589 case GNUNET_CONVERSATION_EC_CALLER_RESUME:
831 set_incoming_call_state(cl->caller,CT_active); 590 set_incoming_call_state(cl,
832 GCG_log (_("Call from `%s' resumed by other user\n"), cl->caller_id); 591 IN_STATE_CONNECTED);
592 GCG_log (_("Call from `%s' resumed by other user\n"),
593 cl->caller_id);
833 break; 594 break;
834 } 595 }
835 do_status(); 596 do_status();
@@ -837,264 +598,125 @@ caller_event_handler (void *cls,
837 598
838 599
839/** 600/**
840 * Start our phone. 601 * The "accept" button was clicked. Accept selected incoming call.
602 *
603 * @param button the button
604 * @param user_data builder (unused)
841 */ 605 */
842static void 606void
843start_phone () 607GNUNET_CONVERSATION_GTK_on_accept_clicked (GtkButton *button,
608 gpointer user_data)
844{ 609{
845 struct GNUNET_GNSRECORD_Data rd; 610 struct IncomingCall *ic;
846 struct GNUNET_IDENTITY_Ego *caller_id;
847 611
848 caller_id = GCG_EGOS_get_selected_ego (); 612 if ( (NULL != active_in) ||
849 if (NULL == caller_id) 613 (NULL != active_out) ||
614 (PS_LISTEN != phone_state) )
850 { 615 {
851 GCG_log ("%s\n", 616 /* accept button should not have been sensitive! */
852 _("No ego selected, phone is now down.")); 617 GNUNET_break (0);
853 phone_state = PS_LOOKUP_EGO;
854 do_status();
855 return;
856 }
857 phone =
858 GNUNET_CONVERSATION_phone_create (GCG_get_configuration (),
859 caller_id,
860 &phone_event_handler,
861 NULL);
862 if (NULL == phone)
863 {
864 GCG_log ("%s",
865 _("Failed to setup phone (internal error)\n"));
866 phone_state = PS_ERROR;
867 do_status();
868 return; 618 return;
869 } 619 }
870 GNUNET_CONVERSATION_phone_get_record (phone, 620 phone_state = PS_ACCEPTED;
871 &rd); 621 ic = NULL; // FIXME: get 'ic' from selection!
872 /* FIXME: publish record to GNS! */ 622 set_incoming_call_state (ic,
873 GCG_log ("%s\n", 623 IN_STATE_CONNECTED);
874 _("Phone active")); 624 GCG_update_status_bar (_("Started a conversation with `%s'.\n"),
875 phone_state = PS_LISTEN; 625 ic->caller_id);
876 do_status(); 626 GCG_set_status_icon ("gnunet-conversation-call-active");
627 GNUNET_CONVERSATION_caller_pick_up (ic->caller,
628 &caller_event_handler, ic,
629 speaker, mic);
630 GCG_HISTORY_add (GCG_HISTORY_TYPE_ACCEPTED,
631 ic->caller_id);
632 // FIXME: update visibility properly...
633 do_status ();
877} 634}
878 635
879 636
880/** 637/**
881 * Function called with an event emitted by a call. 638 * The "reject" button was clicked. Reject incoming call.
882 * 639 *
883 * @param cls closure, NULL 640 * @param button the button
884 * @param code type of the event on the call 641 * @param user_data builder (unused)
885 */ 642 */
886static void 643void
887call_event_handler (void *cls, 644GNUNET_CONVERSATION_GTK_on_reject_clicked (GtkButton *button,
888 enum GNUNET_CONVERSATION_CallEventCode code) 645 gpointer user_data)
889{ 646{
890 //struct OutgoingCallClosure *cl = cls; 647 // do_reject (); // FIXME!
891 648 do_status ();
892 set_outgoing_call_state (NULL, code);
893 switch (code)
894 {
895 case GNUNET_CONVERSATION_EC_CALL_RINGING:
896 GNUNET_break (CS_RESOLVING == call_state);
897 GCG_log (_("Resolved address of `%s'. Now ringing other party."),
898 peer_name);
899 // set_outgoing_call_state(cls, CT_ringing);
900 call_state = CS_RINGING;
901 break;
902 case GNUNET_CONVERSATION_EC_CALL_PICKED_UP:
903 GNUNET_break (CS_RINGING == call_state);
904 GCG_log (_("Connection established to `%s'."),
905 peer_name);
906 call_state = CS_CONNECTED;
907 break;
908 case GNUNET_CONVERSATION_EC_CALL_GNS_FAIL:
909 GNUNET_break (CS_RESOLVING == call_state);
910 GCG_log (_("Failed to resolve %s in current zone."),
911 peer_name);
912 call = NULL;
913 break;
914 case GNUNET_CONVERSATION_EC_CALL_HUNG_UP:
915 GCG_log ("%s", _("Call terminated"));
916 call = NULL;
917 break;
918 case GNUNET_CONVERSATION_EC_CALL_SUSPENDED:
919 GNUNET_break (CS_CONNECTED == call_state);
920 GCG_log (_("Connection to `%s' suspended (by other user)\n"),
921 peer_name);
922 break;
923 case GNUNET_CONVERSATION_EC_CALL_RESUMED:
924 GNUNET_break (CS_CONNECTED == call_state);
925 GCG_log (_("Connection to `%s' resumed (by other user)\n"),
926 peer_name);
927 break;
928 case GNUNET_CONVERSATION_EC_CALL_ERROR:
929 GCG_log ("GNUNET_CONVERSATION_EC_CALL_ERROR %s",
930 peer_name);
931 }
932} 649}
933 650
934 651
935/** 652/**
936 * Initiating a new call 653 * User clicked the '> contact' button to move the selected
654 * caller's information into our address book.
937 * 655 *
938 * @param arg arguments given to the command 656 * @param button the button
657 * @param user_data builder (unused)
939 */ 658 */
940void 659void
941GSC_PHONE_make_call (const char *arg) 660GNUNET_CONVERSATION_GTK_use_current_button_clicked (GtkButton *button,
661 gpointer *user_data)
942{ 662{
943 GtkEntry *address_entry; 663 // FIXME: implement, use "GSC_add_contact"
944 struct GNUNET_IDENTITY_Ego *caller_id; 664#if 0
945 GtkTreeIter gtkiter; 665 const gchar *target;
946 666
947 address_entry = GTK_ENTRY (GCG_get_main_window_object ("GNUNET_GTK_conversation_address")); 667 target = gtk_entry_get_text (address_entry);
948 gtk_entry_set_text (address_entry, 668 gtk_entry_set_text (address_entry,
949 address); 669 "FIXME");
950 caller_id = GCG_EGOS_get_selected_ego (); 670#endif
951 if (NULL == caller_id)
952 {
953 // should not be possible!
954 GCG_log ("%s\n",
955 _("Caller ID unavailable, cannot initiate call."));
956 return;
957 }
958 if (NULL != call)
959 {
960 GCG_log (_("You are calling someone else already, hang up first!\n"));
961 return;
962 }
963 switch (phone_state)
964 {
965 case PS_LOOKUP_EGO:
966 GCG_log ("%s\n",
967 _("Caller ID unavailable, cannot initiate call."));
968 // should not be possible!
969 return;
970 case PS_LISTEN:
971 /* ok to call! */
972 break;
973 case PS_ACCEPTED:
974 GCG_log (_
975 ("You are answering call from `%s', hang up or suspend that call first!\n"),
976 peer_name);
977 GNUNET_break(0);
978 return;
979 case PS_ERROR:
980 /* ok to call */
981 break;
982 }
983 //GNUNET_free_non_null (peer_name);
984 peer_name = GNUNET_strdup (arg);
985 GCG_log (_("now calling: %s"), peer_name);
986 call_state = CS_RESOLVING;
987 GNUNET_assert (NULL == call);
988
989 call_counter++;
990 call =
991 GNUNET_CONVERSATION_call_start (GCG_get_configuration (),
992 caller_id,
993 arg,
994 speaker, mic,
995 &call_event_handler, NULL);
996 //call = newcall;
997
998 // add call to active call list
999
1000 gtk_list_store_append (active_liststore,
1001 &gtkiter);
1002 gtk_list_store_set (active_liststore, &gtkiter,
1003 AL_caller_id, peer_name,
1004 AL_caller, NULL,
1005 AL_caller_num, NULL,
1006 AL_caller_state, CT_other,
1007 AL_type, CALL_OUT,
1008 AL_call, call,
1009 AL_call_num, call_counter,
1010 AL_call_state, CS_RESOLVING,
1011 -1 );
1012 GCG_update_status_bar (_("We are calling `%s', his phone should be ringing."),
1013 peer_name);
1014 GCG_HISTORY_add (GCG_HISTORY_TYPE_OUTGOING,
1015 peer_name);
1016} 671}
1017 672
1018 673
1019/** 674/**
1020 * Accepting an incoming call 675 * The "resume" button was clicked. Resume a call!
1021 * 676 *
1022 * @param args arguments given to the command 677 * @param button the button
678 * @param user_data builder (unused)
1023 */ 679 */
1024static void 680void
1025do_accept (struct GNUNET_CONVERSATION_Caller *sel_caller) 681GNUNET_CONVERSATION_GTK_on_resume_clicked (GtkButton *button,
682 gpointer user_data)
1026{ 683{
1027 struct CallList *cl; 684 enum TypeOfConversation toc;
1028 685 struct IncomingCall *ic;
1029 if ( (NULL != call) && 686 struct OutgoingCall *oc;
1030 (CS_SUSPENDED != call_state) ) 687
688 if ( (NULL != active_in) ||
689 (NULL != active_out) ||
690 (! (PS_LISTEN == phone_state) ||
691 (PS_ERROR == phone_state) ) )
1031 { 692 {
1032 GCG_log (_("You are calling someone else already, hang up first!\n")); 693 /* resume button should have been inactive */
1033 GNUNET_break(0); 694 GNUNET_break(0);
1034 return; 695 return;
1035 } 696 }
1036 switch (phone_state) 697 toc = 42; // FIXME: get from selection!
1037 {
1038 case PS_LOOKUP_EGO:
1039 GNUNET_break (0);
1040 break;
1041 case PS_LISTEN:
1042 /* this is the expected state */
1043 break;
1044 case PS_ACCEPTED:
1045 GCG_log (_
1046 ("You are answering call from `%s', hang up or suspend that call first!\n"),
1047 peer_name);
1048 GNUNET_break(0);
1049 return;
1050 case PS_ERROR:
1051 GNUNET_break (0);
1052 break;
1053 }
1054
1055 phone_state = PS_ACCEPTED;
1056 set_incoming_call_state(sel_caller,CT_active);
1057 698
1058 for (cl = cl_head; cl; cl = cl->next) 699 switch (toc)
1059 { 700 {
1060 /* FIXME: this may not be unique enough to identify the right item! 701 case CALL_IN:
1061 * Why not store CallList items in treeview instead of just callers? 702 ic = NULL; // FIXME: get from selection
1062 */ 703 GNUNET_CONVERSATION_caller_resume (ic->caller, speaker, mic);
1063 if (cl->caller == sel_caller) 704 set_incoming_call_state (ic, IN_STATE_CONNECTED);
1064 break; 705 phone_state = PS_ACCEPTED;
1065 } 706 GCG_update_status_bar (_("Resumed a conversation with `%s'.\n"),
1066 GNUNET_CONVERSATION_caller_pick_up (sel_caller, 707 ic->caller_id);
1067 &caller_event_handler, cl, 708 GCG_set_status_icon ("gnunet-conversation-call-active");
1068 speaker, mic); 709 // FIXME: update visibility/sensitivity
1069 GCG_HISTORY_add (GCG_HISTORY_TYPE_ACCEPTED, peer_name); 710 do_status ();
1070}
1071
1072
1073/**
1074 * Suspending a call
1075 */
1076static void
1077do_suspend ()
1078{
1079 if ( (NULL != call_selected) &&
1080 (NULL != caller_selected) )
1081 {
1082 GNUNET_break(0);
1083 return;
1084 }
1085 if (NULL != call_selected)
1086 {
1087 /* outgoing */
1088 GNUNET_CONVERSATION_call_suspend (call_selected);
1089 set_outgoing_call_state(call_selected,CT_suspended);
1090 return; 711 return;
1091 } 712 case CALL_OUT:
1092 if (NULL != caller_selected) 713 oc = NULL; // FIXME: get from selection
1093 { 714 GNUNET_CONVERSATION_call_resume (oc->call,
1094 /* incoming */ 715 speaker, mic);
1095 GNUNET_CONVERSATION_caller_suspend (caller_selected); 716 set_outgoing_call_state (oc,
1096 set_incoming_call_state(caller_selected,CT_suspended); 717 OUT_STATE_ACTIVE);
1097 phone_state = PS_LISTEN; 718 // FIXME: update visibility/sensitivity
719 do_status ();
1098 return; 720 return;
1099 } 721 }
1100 GNUNET_break (0); 722 GNUNET_break (0);
@@ -1102,82 +724,101 @@ do_suspend ()
1102 724
1103 725
1104/** 726/**
1105 * Resuming a call 727 * The "suspend" button was clicked. Pause a call.
1106 * 728 *
1107 * @param args arguments given to the command 729 * @param button the button
730 * @param user_data builder (unused)
1108 */ 731 */
1109static void 732void
1110do_resume () 733GNUNET_CONVERSATION_GTK_on_pause_clicked (GtkButton *button,
734 gpointer user_data)
1111{ 735{
1112 switch (phone_state) 736 if ( (NULL != active_in) &&
1113 { 737 (NULL != active_out) )
1114 case PS_LOOKUP_EGO:
1115 case PS_ERROR:
1116 GCG_log ("%s",
1117 _("There is no call that could be resumed right now.(PS_ERROR)"));
1118 return;
1119 case PS_LISTEN:
1120 break;
1121 case PS_ACCEPTED:
1122 GCG_log (_("Already talking with `%s', cannot resume a call right now."),
1123 peer_name);
1124 return;
1125 }
1126 if ( (NULL != call_selected) &&
1127 (NULL != caller_selected) )
1128 { 738 {
1129 GNUNET_break(0); 739 GNUNET_break(0);
1130 return; 740 return;
1131 } 741 }
1132 if (NULL != call_selected) 742 if (NULL != active_out)
1133 { 743 {
1134 /* outgoing */ 744 /* outgoing */
1135 GNUNET_CONVERSATION_call_resume (call_selected, speaker, mic); 745 GNUNET_CONVERSATION_call_suspend (active_out->call);
1136 set_outgoing_call_state(call_selected,CT_active); 746 set_outgoing_call_state (active_out,
747 OUT_STATE_SUSPENDED);
748 active_out = NULL;
749 gtk_widget_hide (b_suspend);
750 gtk_widget_hide (b_hangup);
751 gtk_widget_show (b_call);
752 gtk_widget_set_sensitive (b_hangup, FALSE);
753 gtk_widget_set_sensitive (b_suspend, FALSE);
754 gtk_widget_set_sensitive (GTK_WIDGET (address_entry), TRUE);
755 check_call_sensitivity ();
756 do_status ();
757 // FIXME: logging
1137 return; 758 return;
1138 } 759 }
1139 if (NULL != caller_selected) 760 if (NULL != active_in)
1140 { 761 {
1141 /* incoming */ 762 /* incoming */
1142 GNUNET_CONVERSATION_caller_resume (caller_selected, speaker, mic); 763 GNUNET_CONVERSATION_caller_suspend (active_in->caller);
1143 set_incoming_call_state(caller_selected,CT_active); 764 set_incoming_call_state (active_in,
1144 phone_state = PS_ACCEPTED; 765 IN_STATE_SUSPENDED);
766 active_in = NULL;
767 phone_state = PS_LISTEN;
768 // FIXME: visibility
769 // FIXME: logging
1145 return; 770 return;
1146 } 771 }
1147 GNUNET_break(0); 772 GNUNET_break (0);
1148} 773}
1149 774
1150 775
1151/** 776/**
1152 / Rejecting a call 777 * The "hangup" button was clicked. Hang up.
1153 * 778 *
1154 * @param args arguments given to the command 779 * @param button the button
780 * @param user_data builder (unused)
1155 */ 781 */
1156static void 782void
1157do_reject () 783GNUNET_CONVERSATION_GTK_on_hangup_clicked (GtkButton *button,
784 gpointer user_data)
1158{ 785{
1159 if ( (NULL == call_selected) && 786 if ( (NULL == active_in) &&
1160 (NULL == caller_selected) ) 787 (NULL == active_out) )
1161 { 788 {
1162 GNUNET_break(0); 789 GNUNET_break(0);
1163 return; 790 return;
1164 } 791 }
1165 if (NULL != call_selected) 792 if (NULL != active_out)
1166 { 793 {
1167 /* if selected call is outgoing, stop it */ 794 /* if current call is outgoing, stop it */
1168 set_outgoing_call_state (call_selected, CT_hangup); 795 set_outgoing_call_state (active_out,
1169 GNUNET_CONVERSATION_call_stop (call); 796 OUT_STATE_NONE);
1170 call = NULL; 797 // FIXME: rather: remove call state!
1171 call_selected = NULL; 798 GNUNET_CONVERSATION_call_stop (active_out->call);
799 active_out = NULL;
800 // FIXME: logging
801 gtk_widget_hide (b_suspend);
802 gtk_widget_hide (b_hangup);
803 gtk_widget_show (b_call);
804 gtk_widget_set_sensitive (b_hangup, FALSE);
805 gtk_widget_set_sensitive (b_suspend, FALSE);
806 gtk_widget_set_sensitive (GTK_WIDGET (address_entry), TRUE);
807 check_call_sensitivity ();
808 do_status ();
1172 return; 809 return;
1173 } 810 }
1174 if (NULL != caller_selected) 811 if (NULL != active_in)
1175 { 812 {
1176 /* if selected call is incoming, hang it up */ 813 /* if selected call is incoming, hang it up */
1177 set_incoming_call_state (caller_selected,CT_hangup); 814 set_incoming_call_state (active_in,
1178 GNUNET_CONVERSATION_caller_hang_up (caller_selected); 815 IN_STATE_NONE);
816 // FIXME: rather: remove call state!
817 GNUNET_CONVERSATION_caller_hang_up (active_in->caller);
1179 phone_state = PS_LISTEN; 818 phone_state = PS_LISTEN;
1180 caller_selected = NULL; 819 active_in = NULL;
820 // FIXME: logging
821 // FIXME: visibility
1181 return; 822 return;
1182 } 823 }
1183 GNUNET_break (0); 824 GNUNET_break (0);
@@ -1185,98 +826,240 @@ do_reject ()
1185 826
1186 827
1187/** 828/**
1188 * hangup clicked 829 * Function called with an event emitted by a call.
830 *
831 * @param cls our `struct OutgoingCall`
832 * @param code type of the event on the call
1189 */ 833 */
1190void 834static void
1191GNUNET_CONVERSATION_GTK_on_hangup_clicked () 835call_event_handler (void *cls,
836 enum GNUNET_CONVERSATION_CallEventCode code)
1192{ 837{
1193 do_reject (); 838 struct OutgoingCall *oc = cls;
1194 do_status ();
1195}
1196
1197 839
1198/** 840 set_outgoing_call_state (oc, code);
1199 * accept clicked 841 switch (code)
1200 */
1201void
1202GNUNET_CONVERSATION_GTK_on_accept_clicked ()
1203{
1204 if (NULL != caller_selected)
1205 {
1206 do_accept (caller_selected);
1207 }
1208 else
1209 { 842 {
1210 GNUNET_break(0); 843 case GNUNET_CONVERSATION_EC_CALL_RINGING:
844 GNUNET_break (OUT_STATE_RESOLVING == oc->state);
845 GCG_log (_("Resolved address of `%s'. Now ringing other party."),
846 oc->peer_name);
847 // FIXME: use oc->rr here!
848 set_outgoing_call_state (oc, OUT_STATE_RINGING);
849 GCG_log (_("Ringing `%s'.\n"),
850 oc->peer_name);
851 GCG_update_status_bar (_("Ringing `%s'."),
852 oc->peer_name);
853 GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-ringing");
854 break;
855 case GNUNET_CONVERSATION_EC_CALL_PICKED_UP:
856 GNUNET_break (OUT_STATE_RINGING == oc->state);
857 set_outgoing_call_state (oc, OUT_STATE_ACTIVE);
858 gtk_widget_set_sensitive (b_suspend, TRUE);
859 GCG_log (_("Connection established to `%s'."),
860 oc->peer_name);
861 GCG_update_status_bar (_("Talking to `%s'."),
862 oc->peer_name);
863 GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-active");
864 break;
865 case GNUNET_CONVERSATION_EC_CALL_GNS_FAIL:
866 GNUNET_break (OUT_STATE_RESOLVING == oc->state);
867 set_outgoing_call_state (oc, OUT_STATE_NONE);
868 // FIXME: rather: remove from list!
869 GCG_log (_("Failed to resolve %s in current zone."),
870 oc->peer_name);
871 GNUNET_free (oc);
872 active_out = NULL;
873 gtk_widget_hide (b_suspend);
874 gtk_widget_hide (b_hangup);
875 gtk_widget_show (b_call);
876 gtk_widget_set_sensitive (b_hangup, FALSE);
877 gtk_widget_set_sensitive (GTK_WIDGET (address_entry), TRUE);
878 check_call_sensitivity ();
879 do_status ();
880 break;
881 case GNUNET_CONVERSATION_EC_CALL_HUNG_UP:
882 GCG_log ("%s", _("Call terminated"));
883 set_outgoing_call_state (oc, OUT_STATE_NONE);
884 // FIXME: rather: remove from list!
885 GNUNET_free (oc);
886 active_out = NULL;
887 gtk_widget_hide (b_suspend);
888 gtk_widget_hide (b_hangup);
889 gtk_widget_show (b_call);
890 gtk_widget_set_sensitive (b_hangup, FALSE);
891 gtk_widget_set_sensitive (b_suspend, FALSE);
892 gtk_widget_set_sensitive (GTK_WIDGET (address_entry), TRUE);
893 check_call_sensitivity ();
894 do_status ();
895 break;
896 case GNUNET_CONVERSATION_EC_CALL_SUSPENDED:
897 GNUNET_break (OUT_STATE_ACTIVE == oc->state);
898 set_outgoing_call_state (oc, OUT_STATE_SUSPENDED);
899 GCG_log (_("Connection to `%s' suspended (by other user)\n"),
900 oc->peer_name);
901 active_out = NULL;
902 gtk_widget_hide (b_suspend);
903 gtk_widget_hide (b_hangup);
904 gtk_widget_show (b_call);
905 gtk_widget_set_sensitive (b_hangup, FALSE);
906 gtk_widget_set_sensitive (b_suspend, FALSE);
907 gtk_widget_set_sensitive (GTK_WIDGET (address_entry), TRUE);
908 check_call_sensitivity ();
909 do_status ();
910 break;
911 case GNUNET_CONVERSATION_EC_CALL_RESUMED:
912 GNUNET_break (OUT_STATE_ACTIVE == oc->state);
913 GCG_log (_("Connection to `%s' resumed\n"),
914 oc->peer_name);
915 GCG_update_status_bar (_("Talking to `%s'."),
916 oc->peer_name);
917 GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-active");
918 active_out = oc;
919 set_outgoing_call_state (oc, OUT_STATE_ACTIVE);
920 gtk_widget_show (b_suspend);
921 gtk_widget_show (b_hangup);
922 gtk_widget_hide (b_call);
923 gtk_widget_set_sensitive (b_hangup, TRUE);
924 gtk_widget_set_sensitive (b_suspend, TRUE);
925 gtk_widget_set_sensitive (GTK_WIDGET (address_entry), FALSE);
926 break;
927 case GNUNET_CONVERSATION_EC_CALL_ERROR:
928 GCG_log ("GNUNET_CONVERSATION_EC_CALL_ERROR %s",
929 oc->peer_name);
930 set_outgoing_call_state (oc, OUT_STATE_NONE);
931 // FIXME: rather: remove from list!
932 active_out = NULL;
933 gtk_widget_hide (b_suspend);
934 gtk_widget_hide (b_hangup);
935 gtk_widget_show (b_call);
936 gtk_widget_set_sensitive (b_hangup, FALSE);
937 gtk_widget_set_sensitive (b_suspend, FALSE);
938 gtk_widget_set_sensitive (GTK_WIDGET (address_entry), TRUE);
939 check_call_sensitivity ();
940 do_status ();
941 break;
1211 } 942 }
1212 do_status ();
1213} 943}
1214 944
1215 945
1216/** 946/**
1217 * reject clicked 947 * Initiate a new call.
1218 */ 948 *
1219void 949 * @param arg address of the user to call
1220GNUNET_CONVERSATION_GTK_on_reject_clicked ()
1221{
1222 do_reject ();
1223 do_status ();
1224}
1225
1226
1227/**
1228 * User clicked the '> contact' button to move the selected
1229 * caller's information into our address book.
1230 */ 950 */
1231void 951void
1232GNUNET_CONVERSATION_GTK_use_current_button_clicked (GtkButton *button, 952GSC_PHONE_make_call (const char *arg)
1233 gpointer *user_data)
1234{ 953{
1235 // FIXME: implement, use "GSC_add_contact" 954 struct GNUNET_IDENTITY_Ego *caller_id;
1236#if 0 955 GtkTreeIter gtkiter;
1237 GtkEntry *addressEntry; 956 struct OutgoingCall *oc;
1238 957
1239 addressEntry = GTK_ENTRY (GCG_get_main_window_object ("GNUNET_GTK_conversation_addressAdd")); 958 gtk_entry_set_text (address_entry,
1240 gtk_entry_set_text (addressEntry, 959 arg);
1241 "FIXME"); 960 caller_id = GCG_EGOS_get_selected_ego ();
1242#endif 961 if (NULL == caller_id)
962 {
963 /* can happen if user activated address in phone book
964 while our phone was still down (no ego selected) */
965 GCG_log (_("Caller ID unavailable, cannot initiate call to `%s'.\n"),
966 arg);
967 return;
968 }
969 if (NULL != active_out)
970 {
971 if (0 == strcmp (active_out->peer_name,
972 arg))
973 return; /* user likely simply clicked a bit too often, ignore */
974 GCG_log (_("You are on the phone with `%s', suspend or hang up before trying to call `%s'!\n"),
975 active_out->peer_name,
976 arg);
977 return;
978 }
979 switch (phone_state)
980 {
981 case PS_LOOKUP_EGO:
982 GCG_log ("%s\n",
983 _("Caller ID unavailable, cannot initiate call."));
984 return;
985 case PS_LISTEN:
986 /* ok to call! */
987 break;
988 case PS_ACCEPTED:
989 /* `call` should be non-NULL */
990 GNUNET_break (0);
991 return;
992 case PS_ERROR:
993 /* ok to call, we got an ego just could not init the phone */
994 break;
995 }
996 call_counter++;
997 oc = GNUNET_new (struct OutgoingCall);
998 oc->peer_name = GNUNET_strdup (arg);
999 oc->state = OUT_STATE_RESOLVING;
1000 oc->call =
1001 GNUNET_CONVERSATION_call_start (GCG_get_configuration (),
1002 caller_id,
1003 arg,
1004 speaker, mic,
1005 &call_event_handler, oc);
1006 gtk_list_store_insert_with_values (active_liststore,
1007 &gtkiter,
1008 -1,
1009 GCG_PHONE_LS_CALLER_ID, oc->peer_name,
1010 GCG_PHONE_LS_CALLER, NULL,
1011 GCG_PHONE_LS_CALLER_NUM, 0,
1012 GCG_PHONE_LS_CALLER_STATE, IN_STATE_NONE,
1013 GCG_PHONE_LS_TYPE, CALL_OUT,
1014 GCG_PHONE_LS_CALL, oc,
1015 GCG_PHONE_LS_CALL_NUM, call_counter,
1016 GCG_PHONE_LS_CALL_STATE, OUT_STATE_RESOLVING,
1017 -1);
1018 /* log event */
1019 GCG_log (_("Resolving `%s'.\n"),
1020 oc->peer_name);
1021 GCG_update_status_bar (_("Resolving `%s'."),
1022 oc->peer_name);
1023 GCG_set_status_icon ("gnunet-conversation-gtk-tray-call-pending");
1024 GCG_HISTORY_add (GCG_HISTORY_TYPE_OUTGOING,
1025 oc->peer_name);
1026 /* hide "call" button, make address entry insensitive;
1027 show suspend button (but not sensitive),
1028 show hangup button (and make sensitive) */
1029 gtk_widget_hide (b_call);
1030 gtk_widget_set_sensitive (GTK_WIDGET (address_entry), FALSE);
1031 gtk_widget_show (b_suspend);
1032 gtk_widget_show (b_hangup);
1033 gtk_widget_set_sensitive (b_hangup, TRUE);
1243} 1034}
1244 1035
1245 1036
1246/** 1037/**
1247 * pause clicked 1038 * The "connect" button was clicked. Initiate a call!
1248 */ 1039 *
1249void 1040 * @param button the button
1250GNUNET_CONVERSATION_GTK_on_pause_clicked () 1041 * @param user_data builder (unused)
1251{
1252 do_suspend ();
1253 do_status ();
1254}
1255
1256/**
1257 * resume clicked
1258 */ 1042 */
1259void 1043void
1260GNUNET_CONVERSATION_GTK_on_resume_clicked () 1044gnunet_conversation_gtk_call_button_clicked_cb (GtkButton *button,
1045 gpointer user_data)
1261{ 1046{
1262 do_resume (); 1047 GSC_PHONE_make_call (gtk_entry_get_text (address_entry));
1263 do_status ();
1264} 1048}
1265 1049
1266 1050
1267/** 1051/**
1268 * call clicked 1052 * The user has changed the address entry. Consider activating the
1053 * "call" button.
1054 *
1055 * @param editable entry that was changed
1056 * @param user_data builder (unused)
1269 */ 1057 */
1270void 1058void
1271GNUNET_CONVERSATION_GTK_on_call_clicked () 1059gnunet_conversation_gtk_address_entry_changed_cb (GtkEditable *editable,
1060 gpointer user_data)
1272{ 1061{
1273 GtkEntry *address_entry; 1062 check_call_sensitivity ();
1274
1275 address_entry = GTK_ENTRY (GCG_get_main_window_object
1276 ("GNUNET_GTK_conversation_address"));
1277
1278 GSC_PHONE_make_call (gtk_entry_get_text (address_entry));
1279 do_status ();
1280} 1063}
1281 1064
1282 1065
@@ -1290,12 +1073,50 @@ void
1290gnunet_conversation_gtk_ego_combobox_changed_cb (GtkComboBox *widget, 1073gnunet_conversation_gtk_ego_combobox_changed_cb (GtkComboBox *widget,
1291 gpointer user_data) 1074 gpointer user_data)
1292{ 1075{
1076 struct GNUNET_GNSRECORD_Data rd;
1077 struct GNUNET_IDENTITY_Ego *caller_id;
1078
1293 if (NULL != phone) 1079 if (NULL != phone)
1294 { 1080 {
1295 GNUNET_CONVERSATION_phone_destroy (phone); 1081 GNUNET_CONVERSATION_phone_destroy (phone);
1296 phone = NULL; 1082 phone = NULL;
1297 } 1083 }
1298 start_phone(); 1084 caller_id = GCG_EGOS_get_selected_ego ();
1085 if (NULL == caller_id)
1086 {
1087 GCG_update_status_bar ("%s",
1088 _("No ego selected, phone is now down."));
1089 GCG_log ("%s\n",
1090 _("No ego selected, phone is now down."));
1091 GCG_set_status_icon ("gnunet-conversation-gtk-tray-pending");
1092 phone_state = PS_LOOKUP_EGO;
1093 check_call_sensitivity ();
1094 return;
1095 }
1096 phone =
1097 GNUNET_CONVERSATION_phone_create (GCG_get_configuration (),
1098 caller_id,
1099 &phone_event_handler,
1100 NULL);
1101 if (NULL == phone)
1102 {
1103 GCG_update_status_bar ("%s",
1104 _("Failed to setup phone (internal error)\n"));
1105 GCG_log ("%s",
1106 _("Failed to setup phone (internal error)\n"));
1107 GCG_set_status_icon ("gnunet-conversation-offline");
1108 phone_state = PS_ERROR;
1109 check_call_sensitivity ();
1110 return;
1111 }
1112 GNUNET_CONVERSATION_phone_get_record (phone,
1113 &rd);
1114 /* FIXME: publish record to GNS! */
1115 GCG_log ("%s\n",
1116 _("Phone active"));
1117 phone_state = PS_LISTEN;
1118 check_call_sensitivity ();
1119 do_status();
1299} 1120}
1300 1121
1301 1122
@@ -1310,7 +1131,7 @@ GCG_PHONE_init ()
1310 cfg = GCG_get_configuration (); 1131 cfg = GCG_get_configuration ();
1311 speaker = GNUNET_SPEAKER_create_from_hardware (cfg); 1132 speaker = GNUNET_SPEAKER_create_from_hardware (cfg);
1312 mic = GNUNET_MICROPHONE_create_from_hardware (cfg); 1133 mic = GNUNET_MICROPHONE_create_from_hardware (cfg);
1313 /* get gui objects */ 1134
1314 b_add_contact = GTK_WIDGET (GCG_get_main_window_object 1135 b_add_contact = GTK_WIDGET (GCG_get_main_window_object
1315 ("gnunet_conversation_gtk_add_contact_button")); 1136 ("gnunet_conversation_gtk_add_contact_button"));
1316 b_accept = GTK_WIDGET (GCG_get_main_window_object 1137 b_accept = GTK_WIDGET (GCG_get_main_window_object
@@ -1325,7 +1146,8 @@ GCG_PHONE_init ()
1325 ("gnunet_conversation_gtk_call_button")); 1146 ("gnunet_conversation_gtk_call_button"));
1326 b_hangup = GTK_WIDGET (GCG_get_main_window_object 1147 b_hangup = GTK_WIDGET (GCG_get_main_window_object
1327 ("gnunet_conversation_gtk_hangup_button")); 1148 ("gnunet_conversation_gtk_hangup_button"));
1328 1149 address_entry = GTK_ENTRY (GCG_get_main_window_object
1150 ("gnunet_conversation_gtk_address_entry"));
1329 active_liststore = 1151 active_liststore =
1330 GTK_LIST_STORE (GCG_get_main_window_object 1152 GTK_LIST_STORE (GCG_get_main_window_object
1331 ("gnunet_conversation_gtk_active_calls_liststore")); 1153 ("gnunet_conversation_gtk_active_calls_liststore"));
@@ -1341,22 +1163,19 @@ GCG_PHONE_init ()
1341void 1163void
1342GCG_PHONE_shutdown () 1164GCG_PHONE_shutdown ()
1343{ 1165{
1344 struct CallList *cl; 1166 if (NULL != active_in)
1345
1346 while (NULL != (cl = cl_head))
1347 { 1167 {
1348 GNUNET_CONVERSATION_caller_hang_up (cl->caller); 1168 GNUNET_CONVERSATION_caller_hang_up (active_in->caller);
1349 GNUNET_CONTAINER_DLL_remove (cl_head, 1169 // FIXME: memory leak
1350 cl_tail, 1170 active_in = NULL;
1351 cl);
1352 // FIXME: release other memory?
1353 GNUNET_free (cl);
1354 } 1171 }
1355 if (NULL != call) 1172 if (NULL != active_out)
1356 { 1173 {
1357 GNUNET_CONVERSATION_call_stop (call); 1174 GNUNET_CONVERSATION_call_stop (active_out->call);
1358 call = NULL; 1175 // FIXME: memory leak
1176 active_out = NULL;
1359 } 1177 }
1178 // FIXME: clean up tree view!
1360 if (NULL != phone) 1179 if (NULL != phone)
1361 { 1180 {
1362 GNUNET_CONVERSATION_phone_destroy (phone); 1181 GNUNET_CONVERSATION_phone_destroy (phone);
@@ -1366,8 +1185,6 @@ GCG_PHONE_shutdown ()
1366 speaker = NULL; 1185 speaker = NULL;
1367 GNUNET_MICROPHONE_destroy (mic); 1186 GNUNET_MICROPHONE_destroy (mic);
1368 mic = NULL; 1187 mic = NULL;
1369 GNUNET_free_non_null (peer_name);
1370 peer_name = NULL;
1371 phone_state = PS_ERROR; 1188 phone_state = PS_ERROR;
1372} 1189}
1373 1190